#include <stdint.h>

/*
可以利用clang+llvm生成riscv代码，来生成中间代码
clang  -nostdlib -c -target riscv32 -march=rv32imf -O3 armx.c -I ../../../include
ld.lld armx.o -nostdlib -o armx.elf
*/

//主要是处理无符号索引
//在risc系列处理器中，ui 为32有符号位，当调用参数时，会转换为int64_t
#if 0
typedef unsigned int ui;
#else
typedef intptr_t ui;
#endif

#ifndef INLINE
#if defined(__GNUC__)
#define INLINE inline __attribute__((always_inline)) static
#else
#define INLINE inline static
#endif
#endif

static ui abs(ui v){
    if(v<0){
        v = -v;
    }
    return v;
}

enum{
    arm_sp = 13,
    arm_lr = 14,
    arm_pc = 15,
    arm_cpsr,
    arm_spsr = 17,
    arm_fiq_r8,
    arm_fiq_r9,
    arm_fiq_r10,
    arm_fiq_r11,
    arm_fiq_r12,
    arm_fiq_r13,
    arm_fiq_r14,
    arm_fiq_spsr,
    arm_svc_r13,
    arm_svc_r14,
    arm_svc_spsr,
    arm_abt_r13,
    arm_abt_r14,
    arm_abt_spsr,
    arm_irq_r13,
    arm_irq_r14,
    arm_irq_spsr,
    arm_und_r13,
    arm_und_r14,
    arm_und_spsr,
    arm_nflag = 0x40,
    arm_zflag,
    arm_cflag,
    arm_vflag,
    arm_iflag,
    arm_fflag,
    arm_tflag,
    arm_qflag,
    arm_mode,
    arm_ge,

    arm_s_r13,
    arm_s_r14,

    arm_bkpt,
    arm_nextPc,

    arm_svc_state = 0x70,

    arm_old_insn,
    emu_quit,
    emu_state,                  /*模拟器状态*/
    arm_cycles = emu_state,      /*state只取最高的8位*/

#define EMU_STATE_SHIFT_BASE    (24)
#define EMU_STATE_HARDWARE      (24)
/*25有可能往HARDWARE溢出*/
#define EMU_STATE_IO_WRITE (26)
#define EMU_STATE_HALT     (27)
#define EMU_STATE_STOP     (28)
#define EMU_STATE_JMPPC    (29)
#define EMU_REGPC_BREAK(d)  R[emu_state] |= ((d==15)<<EMU_STATE_JMPPC);
#define EMU_JMPPC_BREAK     R[emu_state] |= (1<<EMU_STATE_JMPPC);
/*
由于ARM存在三级流水线.所以,每次读取PC寄存器的时候
其实际值为当前取指令地址+8
此时执行若
    EA000000
    会打断流水线,会跳到当前指令地址+4(跳过一条指令)
    但此时PC寄存器值不变.
    所以需要额外的操作打断CPU流水线

方案1
    外部读取指令时判断写入寄存器是否为PC
方案2
    判断目标写入寄存器是否为PC
方案3
    写入状态寄存器,处理CPU内部中断
方案4
    重写解码器,处理新的影响PC寄存器指令
*/


};

enum{
    arm_mode_fiq = 0b10001,
    arm_mode_irq = 0b10010,
    arm_mode_svc = 0b10011,
    arm_mode_mon = 0b10110,
    arm_mode_abt = 0b10111,
    arm_mode_hyp = 0b11010,
    arm_mode_und = 0b11011,
};

enum{
    armo_lsl,
    armo_lsr,
    armo_asr,
    armo_ror,
    armo_rrx,
};
#ifndef bit
#define bit(v,offset,len)  (((v)>>offset)&((1<<len)-1))
#endif

static uint32_t getbit(uint32_t v,ui m,ui l){
    v>>=l;
    v&=(1<<(m-l+1))-1;
    return v;
}

static int32_t getbits(int32_t v,ui m,ui l){
    v<<=31-m;
    v>>=31-(m-l);
    return v;
}

static uint32_t ror(uint32_t value,int v){
    return ((value>>v)|(value<<(32-v))) & 0xffffffff;
}

#ifndef FASTSAT
#define FASTSAT 1
#endif

//存储操作
#if 1
extern uint32_t read_u32 (uint32_t*R,uint32_t address);
extern uint32_t read_u16 (uint32_t*R,uint32_t address);
extern uint32_t read_u8  (uint32_t*R,uint32_t address);
extern uint32_t read_s16 (uint32_t*R,uint32_t address);
extern uint32_t read_s8  (uint32_t*R,uint32_t address);
extern void write_u32    (uint32_t*R,uint32_t rd,uint32_t address);
extern void write_u16    (uint32_t*R,uint32_t rd,uint32_t address);
extern void write_u8     (uint32_t*R,uint32_t rd,uint32_t address);
extern void write_u64    (uint32_t*R,uint32_t rd,uint32_t address);
extern void read_u64     (uint32_t*R,uint32_t rd,uint32_t address);
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef int64_t s64;
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t  s8;
static uint32_t     cpu_getpc   (uint32_t *R){
    return R[arm_pc];
}

static void jmp_abs  (uint32_t *R,ui address){
    R[arm_pc] = address;
    R[arm_tflag] = address&1;
    EMU_JMPPC_BREAK
}

extern void cpu_bkpt    (uint32_t *R,uint32_t value);
extern void cpu_svc     (uint32_t *R,int imm);
extern void cpu_undefined_instruction(uint32_t*R);

#elif !defined(XCPUX_GENERIC)
#include <xcpux.h>
/*
使用命令编译成riscv
    clang -nostdlib -c armx.c -o armx.elf -O2 --target=riscv32 -march=rv32i -I../../include
*/
typedef uint32_t (*mr)(void*R,uint32_t addr);
typedef void     (*mw)(void*R,uint32_t addr,uint32_t value);

static uint32_t read_u32 (void*R,uint32_t address){
    uint32_t *r = (uint32_t*)R;
    return (*(mr*)(r + xcpu_internal_read_u32 ))(R,address);
}
static uint32_t read_u16 (void*R,uint32_t address){
    uint32_t *r = (uint32_t*)R;
    return (*(mr*)(r + xcpu_internal_read_u16 ))(R,address);
}
static uint32_t read_u8  (void*R,uint32_t address){
    uint32_t *r = (uint32_t*)R;
    return (*(mr*)(r + xcpu_internal_read_u8 ))(R,address);
}
static uint32_t read_s16 (void*R,uint32_t address){
    uint32_t *r = (uint32_t*)R;
    return (*(mr*)(r + xcpu_internal_read_s16 ))(R,address);
}
static uint32_t read_s8  (void*R,uint32_t address){
    uint32_t *r = (uint32_t*)R;
    return (*(mr*)(r + xcpu_internal_read_s8 ))(R,address);
}

static void write_u32    (void*R,uint32_t rd,uint32_t address){
    uint32_t *r = (uint32_t*)R;
    (*(mw*)(r + xcpu_internal_write_u32))(R,rd,address);
}
static void write_u16    (void*R,uint32_t rd,uint32_t address){
    uint32_t *r = (uint32_t*)R;
    (*(mw*)(r + xcpu_internal_write_u16))(R,rd,address);
}
static void write_u8     (void*R,uint32_t rd,uint32_t address){
    uint32_t *r = (uint32_t*)R;
    (*(mw*)(r + xcpu_internal_write_u8))(R,rd,address);
}

static void write_u64    (void*R,uint32_t rd,uint32_t address){
    uint32_t *r = (uint32_t*)R;
    (*(mw*)(r + xcpu_internal_write_u64))(R,rd,address);
}
static void read_u64     (void*R,uint32_t rd,uint32_t address){
    uint32_t *r = (uint32_t*)R;
    (*(mw*)(r + xcpu_internal_read_u64))(R,rd,address);
}

typedef u32 (*jmp_func_t)(uint32_t *R,int32_t offset);
//跳转操作
static void jmp_rel  (uint32_t *R,int32_t offset){
    (*(jmp_func_t*)(R + xcpu_internal_jmp_rel))(R,offset);
}
static void jmp_abs  (uint32_t *R,int32_t address){
    (*(jmp_func_t*)(R + xcpu_internal_jmp_abs))(R,address);
}
static void jmp_reg  (uint32_t *R,int32_t reg){
    (*(jmp_func_t*)(R + xcpu_internal_jmp_reg))(R,reg);
}
//其他指令
static void         cpu_bkpt    (uint32_t *R,uint32_t value){
    (*(jmp_func_t*)(R + xcpu_internal_bkpt))(R,value);
}
static uint32_t     cpu_getpc   (uint32_t *R){
    return (*(jmp_func_t*)(R + xcpu_internal_getpc))(R,0);
}
static void         cpu_svc     (uint32_t *R,int imm){
    (*(jmp_func_t*)(R + xcpu_internal_svc))(R,imm);
}

static void         cpu_undefined_instruction(uint32_t*R){
    (*(jmp_func_t*)(R + xcpu_internal_undefined_instruction))(R,0);
}
uint32_t *xcpu_getregptr(xcpux_t*cpu){
    return cpu->reg;
}
#else
extern uint32_t read_u32 (void*R,uint32_t address);
extern uint32_t read_u16 (void*R,uint32_t address);
extern uint32_t read_u8  (void*R,uint32_t address);
extern uint32_t read_s16 (void*R,uint32_t address);
extern uint32_t read_s8  (void*R,uint32_t address);
extern void write_u32    (void*R,uint32_t rd,uint32_t address);
extern void write_u16    (void*R,uint32_t rd,uint32_t address);
extern void write_u8     (void*R,uint32_t rd,uint32_t address);
extern void write_u64    (void*R,uint32_t rd,uint32_t address);
extern void read_u64     (void*R,uint32_t rd,uint32_t address);
//跳转操作
extern void jmp_rel  (uint32_t *R,ui offset);
extern void jmp_abs  (uint32_t *R,ui address);
extern void jmp_reg  (uint32_t *R,ui reg);

//其他指令
extern void         cpu_bkpt    (uint32_t *R,uint32_t value);
extern uint32_t     cpu_getpc   (uint32_t *R);
extern void         cpu_svc     (uint32_t *R,ui imm);
extern void         cpu_undefined_instruction(uint32_t*R);
#endif

static uint32_t Shift_C(uint32_t *carry,uint32_t value,ui type,ui amount,ui c){
#if 1
    //最初版本，正确
    switch (type)
    {
    case armo_lsl:{
        *carry = ((int32_t)value<<(amount-1)) <0?1:0;
        return value<<amount;
    }
    break;
    case armo_lsr:{
        *carry = (value>>(amount-1))&1;
        return value>>amount;
    }
    break;
    case armo_asr:{
        *carry = (value>>(amount-1))&1;
        return (int32_t)value>>amount;
    }
    break;
    case armo_ror:{
        uint32_t hi = value<<(32-amount);
        uint32_t lo = value>>(amount);
        int32_t  result = hi|lo;
        *carry = result<0?1:0;
        return result;
    }
    break;
    case armo_rrx:{
        *carry = value&1;
        uint32_t result = (amount<<31)|(value>>1);
        return result;
    }
    break;

    default:
        break;
    }
#else
    switch (type)
    {
    case armo_lsl:{
        #if 1
        if(amount){
            *carry = (value>>(32-amount)) &1?1:0;
        }
        return value<<amount;
        #else
        value <<= (amount-1);
        *carry = (int32_t)value < 0;
        return value<<1;
        #endif
    }
    break;
    case armo_lsr:{
        *carry = (value>>(amount-1))&1;
        return value>>amount;
    }
    break;
    case armo_asr:{
        #if 0
        if(amount<32){
            *carry = ((int32_t)value>>(int32_t)(amount-1))&1;
        }
        else{

            if(value&0x80000000){
                *carry = 1;
                return 0xffffffff;
            }
            else{
                *carry = 0;
                return 0;
            }
        }
        return (int32_t)value>>(int32_t)amount;
        #else
        *carry = ((int32_t)value>>(int32_t)(amount-1))&1;
        return (int32_t)value>>(int32_t)amount;
        #endif
    }
    break;
    case armo_ror:{
        uint32_t hi = value<<(32-amount);
        uint32_t lo = value>>(amount);
        uint32_t  result = hi|lo;
        *carry = result<0?1:0;
        return result;
    }
    break;

    default:
        break;
    }
#endif
    return 0;
}

static uint32_t Shift(uint32_t value,ui type,ui amount){
    uint32_t c;
    return Shift_C(&c,value,type,amount,0);
}

static uint32_t AddWithCarry(uint32_t*carry,uint32_t *overflow,uint32_t Rn,uint32_t shifted,ui c){
#if 0
    //需要64位cpu处理才快，带跳转
    //正确
    int64_t  ssum = (int64_t)(int32_t)Rn+ (int64_t)(int32_t)shifted + c;
    uint64_t usum = (uint64_t)Rn        + (uint64_t)shifted + c;
    uint32_t result = (uint32_t)usum;
    *carry      = usum==result?0:1;
    *overflow   = ssum==(int32_t)result?0:1;
#elif 0
    //无分支,无跳转指令
    uint32_t result = Rn + shifted + c;
    *carry =
      ((Rn>>31)&(shifted>>31))       /*rn和rs同时大于0x80000000,则溢出*/
    | ((Rn>>31)&(~result>>31))       /*如果结果小于Rn,则溢出*/
    | ((shifted>>31)&(~result>>31)); /*如果结果小于Rs,则溢出*/

    *overflow =
        ((Rn>>31)&(shifted>>31)&(~result>>31))    /*rn和rs同时为负数,结果为正数*/
        |((~Rn>>31)&(~shifted>>31)&(result>>31)); /*rn和rs同时为正数,结果为负数*/
#elif 1
    //无分支,无跳转指令
    /*
    一般溢出的结果,都应该比Rn,shifted小
        负数+负数=更小的负数
    */
    uint32_t result = Rn + shifted + c;
    #if 0
    *carry =
        ((int32_t)Rn<0&(int32_t)shifted<0)
        | ((int32_t)Rn<0&(result>=0))
        | ((int32_t)shifted<0&(result>=0));
    #else
    *carry =
        (((int32_t)Rn<0)&((int32_t)shifted<0))
        |(((int32_t)result>=0)&(((int32_t)Rn<0)|((int32_t)shifted<0)));
    #endif

    *overflow =
        (((int32_t)Rn<0) & ((int32_t)shifted<0) & ((int32_t)result>=0))
        |(((int32_t)Rn>=0)& ((int32_t)shifted>=0) & ((int32_t)result<0));
#endif
    return (uint32_t)result;
}

static uint32_t _adc(uint32_t*reg,uint32_t rn,uint32_t shifted,ui S,ui ic){
    uint32_t c,v;
    uint32_t result = AddWithCarry(&c,&v,rn,shifted,ic);
    if(S){
        reg[arm_zflag] = result==0?1:0;
        reg[arm_nflag] = (int32_t)result <0?1:0;
        reg[arm_cflag] = c;
        reg[arm_vflag] = v;
    }
    return result;
}

static void setflag(uint32_t*reg,uint32_t result,ui S,uint32_t c,uint32_t *o){
    if(S){
        reg[arm_zflag] = result==0?1:0;
        reg[arm_nflag] = (int32_t)result<0?1:0;
        reg[arm_cflag] = c;
        if(o){
            reg[arm_vflag] = *o;
        }
    }
}

static void _setflag(uint32_t*reg,uint32_t result,ui S,uint32_t *c,uint32_t *o){
    if(S){
        reg[arm_zflag] = result==0?1:0;
        reg[arm_nflag] = (int32_t)result<0?1:0;
        if(c){
            reg[arm_cflag] = *c;
        }
        if(o){
            reg[arm_vflag] = *o;
        }
    }
}

static uint32_t _and(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    uint32_t result = op1 & op2;
    setflag(reg,result,S,c,0);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

static uint32_t _bic(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    uint32_t result = _and(R,rd,op1,~op2,reg,S,c);
    return result;
}

static uint32_t _eor(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    uint32_t result = op1^op2;
    setflag(reg,result,S,c,0);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

static uint32_t _mvn(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    uint32_t result = ~op2;
    setflag(reg,result,S,c,0);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

#define def_name(shift) and_##shift
#define _opr _and
#include "arm_shift.h"
#undef def_name
#undef _opr

#define def_name(shift) bic_##shift
#define _opr _bic
#include "arm_shift.h"
#undef def_name
#undef _opr

#define def_name(shift) eor_##shift
#define _opr _eor
#include "arm_shift.h"
#undef def_name
#undef _opr

#define def_name(shift) mvn_##shift
#define _opr _mvn
#include "arm_shift.h"
#undef def_name
#undef _opr

static uint32_t _orr(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    uint32_t result = op1|op2;
    setflag(reg,result,S,c,0);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

#define def_name(shift) orr_##shift
#define _opr _orr
#include "arm_shift.h"
#undef def_name
#undef _opr

static uint32_t _add(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    //uint32_t result = op1|op2;
    uint32_t o;
    uint32_t result = AddWithCarry(&c,&o,op1,op2,0);
    setflag(reg,result,S,c,&o);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

#define def_name(shift) add_##shift
#define _opr _add
#include "arm_shift.h"
#undef def_name
#undef _opr

static uint32_t _sub(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    //uint32_t result = op1|op2;
    uint32_t o;
    uint32_t result = AddWithCarry(&c,&o,op1,~op2,1);
    setflag(reg,result,S,c,&o);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

#define def_name(shift) sub_##shift
#define _opr _sub
#include "arm_shift.h"
#undef def_name
#undef _opr

static uint32_t __adc(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    //uint32_t result = op1|op2;
    uint32_t o;
    uint32_t result = AddWithCarry(&c,&o,op1,op2,reg[arm_cflag]);
    setflag(reg,result,S,c,&o);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

#define def_name(shift) adc_##shift
#define _opr __adc
#include "arm_shift.h"
#undef def_name
#undef _opr

static uint32_t _sbc(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    //uint32_t result = op1|op2;
    uint32_t o;
    uint32_t result = AddWithCarry(&c,&o,op1,~op2,reg[arm_cflag]);
    setflag(reg,result,S,c,&o);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

#define def_name(shift) sbc_##shift
#define _opr _sbc
#include "arm_shift.h"
#undef def_name
#undef _opr

static uint32_t _rsb(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    //uint32_t result = op1|op2;
    uint32_t o;
    uint32_t result = AddWithCarry(&c,&o,~op1,op2,1);
    setflag(reg,result,S,c,&o);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

#define def_name(shift) rsb_##shift
#define _opr _rsb
#include "arm_shift.h"
#undef def_name
#undef _opr

static uint32_t _rsc(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    //uint32_t result = op1|op2;
    uint32_t o;
    uint32_t result = AddWithCarry(&c,&o,~op1,op2,reg[arm_cflag]);
    setflag(reg,result,S,c,&o);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

#define def_name(shift) rsc_##shift
#define _opr _rsc
#include "arm_shift.h"
#undef def_name
#undef _opr

static uint32_t _mov(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    uint32_t result = op2;
    setflag(reg,result,S,c,0);
    EMU_REGPC_BREAK(rd);
    R[rd] = result;
    return result;
}

#define def_name(shift) mov_##shift
#define _opr _mov
#include "arm_shift.h"
#undef def_name
#undef _opr

//比较操作
static uint32_t _cmp(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    uint32_t o;
    uint32_t result = AddWithCarry(&c,&o,op1,~op2,1);
    setflag(reg,result,S,c,&o);
    return result;
}

#define def_name(shift) cmp_##shift
#define _opr _cmp
#include "arm_shift.h"
#undef def_name
#undef _opr

static uint32_t _cmn(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    uint32_t o;
    uint32_t result = AddWithCarry(&c,&o,op1,op2,0);
    setflag(reg,result,S,c,&o);
    return result;
}

#define def_name(shift) cmn_##shift
#define _opr _cmn
#include "arm_shift.h"
#undef def_name
#undef _opr

//比较操作
static uint32_t _tst(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    //uint32_t result = op1|op2;
    uint32_t o;
    uint32_t result = op1&op2;
    setflag(reg,result,S,c,&o);
    //R[rd] = result;
    return result;
}

#define def_name(shift) tst_##shift
#define _opr _tst
#include "arm_shift.h"
#undef def_name
#undef _opr

static uint32_t _teq(uint32_t*R,ui rd,uint32_t op1,uint32_t op2,uint32_t*reg,ui S,uint32_t c){
    //uint32_t result = op1|op2;
    uint32_t o;
    uint32_t result = op1^op2;
    setflag(reg,result,S,c,&o);
    //R[rd] = result;
    return result;
}

#define def_name(shift) teq_##shift
#define _opr _teq
#include "arm_shift.h"
#undef def_name
#undef _opr

enum{
    arms_readu32,
    arms_readu16,
    arms_readu8,
    arms_reads16,
    arms_reads8,

    arms_writeu32,
    arms_writeu16,
    arms_writeu8,
    arms_readu64,
    arms_writeu64,
};

static void _storage(uint32_t*R,ui store,ui add,ui index,ui wback,ui t,ui n,ui m,ui shift_t,ui shift_n,ui isreg){
    uint32_t offset;
    uint32_t rn_addr = R[n];
    #if 0
    if(n==arm_pc){
        rn_addr &= ~0x3;
    }
    #else
    int32_t v = n-arm_pc;
    v = -v|v;
    v >>= 31;
    /*
    如果n为arm_pc,则v=0,否则v=-1
    */
    rn_addr &= (~0x3)|v;
    #endif
    if(isreg){
        offset = Shift(R[m],shift_t,shift_n);
    }
    else{
        offset = m;
    }
    uint32_t offset_addr =  add?rn_addr+offset:rn_addr-offset;
    uint32_t address =      index?offset_addr:rn_addr;
    switch (store)
    {
    case arms_readu32:EMU_REGPC_BREAK(t); R[t] = read_u32(R,address);break;
    case arms_readu16:R[t] = read_u16(R,address);break;
    case arms_readu8 :R[t] = read_u8(R,address);break;
    case arms_reads16:R[t] = read_s16(R,address);break;
    case arms_reads8 :R[t] = read_s8(R,address);break;
    case arms_readu64:R[t] = read_u32(R,address);R[t+1] = read_u32(R,address+4); break;
    case arms_writeu32:      write_u32(R,R[t],address);break;
    case arms_writeu16:      write_u16(R,R[t],address);break;
    case arms_writeu8 :      write_u8(R, R[t],address);break;
    //case arms_writeu64:      write_u64(R,R[t],address);break;
    default:
        break;
    }

    if(wback){
        R[n] = offset_addr;
    }
}

static void _storagex(uint32_t*R,ui type,ui shift_t,ui U,ui P,ui W,ui t,ui n,ui m,ui shift_n,ui isreg){
    ui add = U==0?0:1;
    ui index = P!=0;
    ui wback = (P==0)||(W==1);
    _storage(R,type,add,index,wback,t,n,m,shift_t,shift_n,isreg);
}

#define def_storage(name,type,U,P,W) \
void name##_lsl(uint32_t*R,ui t,ui n,ui m,ui shift_n){     \
    _storagex(R,type,armo_lsl,U,P,W,t,n,m,shift_n,1); \
} \
void name##_lsr(uint32_t*R,ui t,ui n,ui m,ui shift_n){     \
    _storagex(R,type,armo_lsr,U,P,W,t,n,m,shift_n,1); \
} \
void name##_asr(uint32_t*R,ui t,ui n,ui m,ui shift_n){     \
    _storagex(R,type,armo_asr,U,P,W,t,n,m,shift_n,1); \
} \
void name##_ror(uint32_t*R,ui t,ui n,ui m,ui shift_n){     \
    _storagex(R,type,armo_ror,U,P,W,t,n,m,shift_n,1); \
} \
void name##imm(uint32_t*R,ui t,ui n,uint32_t m){     \
    _storagex(R,type,armo_lsl,U,P,W,t,n,m,0,0); \
}

def_storage(ldr1,arms_readu32,1,0,1);    //U=1,P=0,W=0
def_storage(ldr2,arms_readu32,1,1,1);    //U=1,P=1,W=1
def_storage(ldr3,arms_readu32,1,1,0);    //U=1,P=1,W=0
def_storage(ldrb1,arms_readu8,1,0,1);    //U=1,P=0,W=0
def_storage(ldrb2,arms_readu8,1,1,1);    //U=1,P=1,W=1
def_storage(ldrb3,arms_readu8,1,1,0);    //U=1,P=1,W=0
def_storage(ldr1s,arms_readu32,0,0,1);   //U=0,P=0,W=0
def_storage(ldr2s,arms_readu32,0,1,1);   //U=0,P=1,W=1
def_storage(ldr3s,arms_readu32,0,1,0);   //U=0,P=1,W=0
def_storage(ldrb1s,arms_readu8,0,0,1);   //U=0,P=0,W=0
def_storage(ldrb2s,arms_readu8,0,1,1);   //U=0,P=1,W=1
def_storage(ldrb3s,arms_readu8,0,1,0);   //U=0,P=1,W=0


def_storage(str1,arms_writeu32,1,0,1);    //U=1,P=0,W=0
def_storage(str2,arms_writeu32,1,1,1);    //U=1,P=1,W=1
def_storage(str3,arms_writeu32,1,1,0);    //U=1,P=1,W=0
def_storage(strb1,arms_writeu8,1,0,1);    //U=1,P=0,W=0
def_storage(strb2,arms_writeu8,1,1,1);    //U=1,P=1,W=1
def_storage(strb3,arms_writeu8,1,1,0);    //U=1,P=1,W=0
def_storage(str1s,arms_writeu32,0,0,1);   //U=0,P=0,W=0
def_storage(str2s,arms_writeu32,0,1,1);   //U=0,P=1,W=1
def_storage(str3s,arms_writeu32,0,1,0);   //U=0,P=1,W=0
def_storage(strb1s,arms_writeu8,0,0,1);   //U=0,P=0,W=0
def_storage(strb2s,arms_writeu8,0,1,1);   //U=0,P=1,W=1
def_storage(strb3s,arms_writeu8,0,1,0);   //U=0,P=1,W=0

#define def_storage2(name,type,U,P,W) \
void name##_reg(uint32_t*R,ui t,ui n,ui m){     \
    _storagex(R,type,armo_lsl,U,P,W,t,n,m,0,1); \
} \
void name##_imm(uint32_t*R,ui t,ui n,uint32_t imm4h,uint32_t imm4l){     \
    _storagex(R,type,armo_lsl,U,P,W,t,n,(imm4h<<4)|imm4l,0,0); \
}

def_storage2(ldrh1, arms_readu16,1,0,1);    //U=1,P=0,W=0
def_storage2(ldrh2, arms_readu16,1,1,1);    //U=1,P=1,W=1
def_storage2(ldrh3, arms_readu16,1,1,0);    //U=1,P=1,W=0
def_storage2(ldrh1s,arms_readu16,0,0,1);    //U=0,P=0,W=0
def_storage2(ldrh2s,arms_readu16,0,1,1);    //U=0,P=1,W=1
def_storage2(ldrh3s,arms_readu16,0,1,0);    //U=0,P=1,W=0

def_storage2(ldrsh1, arms_reads16,1,0,1);    //U=1,P=0,W=0
def_storage2(ldrsh2, arms_reads16,1,1,1);    //U=1,P=1,W=1
def_storage2(ldrsh3, arms_reads16,1,1,0);    //U=1,P=1,W=0
def_storage2(ldrsh1s,arms_reads16,0,0,1);    //U=0,P=0,W=0
def_storage2(ldrsh2s,arms_reads16,0,1,1);    //U=0,P=1,W=1
def_storage2(ldrsh3s,arms_reads16,0,1,0);    //U=0,P=1,W=0

def_storage2(strh1, arms_writeu16,1,0,1);    //U=1,P=0,W=0
def_storage2(strh2, arms_writeu16,1,1,1);    //U=1,P=1,W=1
def_storage2(strh3, arms_writeu16,1,1,0);    //U=1,P=1,W=0
def_storage2(strh1s,arms_writeu16,0,0,1);    //U=0,P=0,W=0
def_storage2(strh2s,arms_writeu16,0,1,1);    //U=0,P=1,W=1
def_storage2(strh3s,arms_writeu16,0,1,0);    //U=0,P=1,W=0

def_storage2(ldrsb1, arms_reads8,1,0,1);    //U=1,P=0,W=0
def_storage2(ldrsb2, arms_reads8,1,1,1);    //U=1,P=1,W=1
def_storage2(ldrsb3, arms_reads8,1,1,0);    //U=1,P=1,W=0
def_storage2(ldrsb1s,arms_reads8,0,0,1);    //U=0,P=0,W=0
def_storage2(ldrsb2s,arms_reads8,0,1,1);    //U=0,P=1,W=1
def_storage2(ldrsb3s,arms_reads8,0,1,0);    //U=0,P=1,W=0

def_storage2(strd1, arms_writeu64,1,0,1);    //U=1,P=0,W=0
def_storage2(strd2, arms_writeu64,1,1,1);    //U=1,P=1,W=1
def_storage2(strd3, arms_writeu64,1,1,0);    //U=1,P=1,W=0
def_storage2(ldrd1, arms_readu64,1,0,1);    //U=1,P=0,W=0
def_storage2(ldrd2, arms_readu64,1,1,1);    //U=1,P=1,W=1
def_storage2(ldrd3, arms_readu64,1,1,0);    //U=1,P=1,W=0

def_storage2(strd1s, arms_writeu64,1,0,1);    //U=1,P=0,W=0
def_storage2(strd2s, arms_writeu64,1,1,1);    //U=1,P=1,W=1
def_storage2(strd3s, arms_writeu64,1,1,0);    //U=1,P=1,W=0
def_storage2(ldrd1s, arms_readu64,1,0,1);    //U=1,P=0,W=0
def_storage2(ldrd2s, arms_readu64,1,1,1);    //U=1,P=1,W=1
def_storage2(ldrd3s, arms_readu64,1,1,0);    //U=1,P=1,W=0

// void bl(uint32_t*R,uint32_t value){
//     value<<=8;
//     value = (int32_t)value>>6; //*2
//     R[arm_lr] = cpu_getpc(R) + 4;
//     jmp_rel(R,value);
// }

void b(uint32_t*R,int32_t imm){
    imm<<=(32-24);
    imm>>=(32-26);
    jmp_abs(R,R[arm_pc]+imm);
}

void blx(uint32_t*R,uint32_t rx){
    R[arm_lr] = cpu_getpc(R) + 4;
    jmp_abs(R,R[rx]);
}

void blx_imm(uint32_t*R,int32_t imm){
    imm<<=(32-24);
    imm>>=(32-26);
    R[arm_lr] = cpu_getpc(R) + 4;
    jmp_abs(R,R[arm_pc]+imm);
}

void bx(uint32_t*R,uint32_t rx){
    jmp_abs(R,R[rx]);
}

void bkpt(uint32_t*R,ui imm12,ui imm4){
    uint32_t imm = (imm12<<4)|imm4;
    cpu_bkpt(R,imm);
}

void bl(uint32_t*R,ui imm){
    imm<<=(32-24);
    imm>>=(32-24);
    imm<<= 2;
    R[arm_lr] = R[arm_pc] - 4;
    uint32_t pc = (R[arm_pc]&~0x3) + imm;
    jmp_abs(R,pc);
}

static void _ldm(uint32_t*R,ui rn,ui list,ui W){
    uint32_t address = R[rn];
    ui i;
    for(i=0;i<16;i++){
        if(list&(1<<i)){
            EMU_REGPC_BREAK(i);
            R[i] = read_u32(R,address);
            address += 4;
        }
    }
    if(W){
        R[rn] = address;
    }
}

static void _ldmda(uint32_t*R,ui rn,ui list,ui W){
    uint32_t address = R[rn];
    ui i;
    for(i=15;i>=0;i--){
        if(list&(1<<i)){
            EMU_REGPC_BREAK(i);
            R[i] = read_u32(R,address);
            address -= 4;
        }
    }
    if(W){
        R[rn] = address;
    }
}

static void _ldmdb(uint32_t*R,ui rn,ui list,ui W){
    uint32_t address = R[rn];
    ui i;
    for(i=15;i>=0;i--){
        if(list&(1<<i)){
            address -= 4;
            EMU_REGPC_BREAK(i);
            R[i] = read_u32(R,address);
        }
    }
    if(W){
        R[rn] = address;
    }
}

static void _ldmib(uint32_t*R,ui rn,ui list,ui W){
    uint32_t address = R[rn];
    ui i;
    for(i=0;i<16;i++){
        if(list&(1<<i)){
            address += 4;
            EMU_REGPC_BREAK(i);
            R[i] = read_u32(R,address);
        }
    }
    if(W){
        R[rn] = address;
    }
}

INLINE void _stm(uint32_t*R,ui rn,ui list,ui W){
    uint32_t address = R[rn];
    ui i;
    for(i=0;i<16;i++){
        if(list&(1<<i)){
            //R[i] = read_u32(R,address);
            write_u32(R,R[i],address);
            address += 4;
        }
    }
    if(W){
        R[rn] = address;
    }
}

INLINE void _stmda(uint32_t*R,ui rn,ui list,ui W){
    uint32_t address = R[rn];
    ui i;
    for(i=15;i>=0;i--){
        if(list&(1<<i)){
            //R[i] = read_u32(R,address);
            write_u32(R,R[i],address);
            address -= 4;
        }
    }
    if(W){
        R[rn] = address;
    }
}

INLINE void _stmdb(uint32_t*R,ui rn,ui list,ui W){
    uint32_t address = R[rn];
    ui i;
    for(i=15;i>=0;i--){
        if(list&(1<<i)){
            address -= 4;
            //R[i] = read_u32(R,address);
            write_u32(R,R[i],address);
        }
    }
    if(W){
        R[rn] = address;
    }
}

INLINE void _stmib(uint32_t*R,ui rn,ui list,ui W){
    uint32_t address = R[rn];
    ui i;
    for(i=0;i<16;i++){
        if(list&(1<<i)){
            address += 4;
            //R[i] = read_u32(R,address);
            write_u32(R,R[i],address);
        }
    }
    if(W){
        R[rn] = address;
    }
}

void stm    (uint32_t*R,ui rn,ui list){ _stm(R,rn,list,  0);};
void stmib  (uint32_t*R,ui rn,ui list){ _stmib(R,rn,list,0);};
void stmda  (uint32_t*R,ui rn,ui list){ _stmda(R,rn,list,0);};
void stmdb  (uint32_t*R,ui rn,ui list){ _stmdb(R,rn,list,0);};
void stm_w  (uint32_t*R,ui rn,ui list){ _stm(R,rn,list,  1);};
void stmib_w(uint32_t*R,ui rn,ui list){ _stmib(R,rn,list,1);};
void stmda_w(uint32_t*R,ui rn,ui list){ _stmda(R,rn,list,1);};
void stmdb_w(uint32_t*R,ui rn,ui list){ _stmdb(R,rn,list,1);};

void ldm    (uint32_t*R,ui rn,ui list){ _ldm(R,rn,list,  0);};
void ldmib  (uint32_t*R,ui rn,ui list){ _ldmib(R,rn,list,0);};
void ldmda  (uint32_t*R,ui rn,ui list){ _ldmda(R,rn,list,0);};
void ldmdb  (uint32_t*R,ui rn,ui list){ _ldmdb(R,rn,list,0);};
void ldm_w  (uint32_t*R,ui rn,ui list){ _ldm(R,rn,list,  1);};
void ldmib_w(uint32_t*R,ui rn,ui list){ _ldmib(R,rn,list,1);};
void ldmda_w(uint32_t*R,ui rn,ui list){ _ldmda(R,rn,list,1);};
void ldmdb_w(uint32_t*R,ui rn,ui list){ _ldmdb(R,rn,list,1);};

static void _mla(uint32_t *R,ui S,ui d,ui n,ui m,ui a){
    int32_t operand1 = (int32_t)R[n];
    int32_t operand2 = (int32_t)R[m];
    int32_t addend = (int32_t)R[a];
    R[d] = operand1 * operand2 + addend;
    if(S){
        R[arm_nflag] = (int32_t)R[d]<0?1:0;
        R[arm_zflag] = R[d]==0?1:0;
    }
}

void mla(uint32_t *R,ui d,ui n,ui m,ui a){ return _mla(R,0,d,n,m,a);}
void mlaS(uint32_t *R,ui d,ui n,ui m,ui a){ return _mla(R,1,d,n,m,a);}

void mls(uint32_t*R,ui d,ui n,ui m,ui a){
    int32_t operand1 = (int32_t)R[n];
    int32_t operand2 = (int32_t)R[m];
    int32_t addend = (int32_t)R[a];
    int32_t result = addend - operand1 * operand2;
    R[d] = result;
}

static void _mul(uint32_t*R,ui S,ui d,ui n,ui m){
    R[d] = R[n] * R[m];
    _setflag(R,R[d],S,0,0);
}

static void pkh(uint32_t*R,ui tbform,ui d,ui n,ui m,ui shift_t,ui shift_n){
    uint32_t op2 = Shift(R[m],shift_t,shift_n);
    if(tbform){
        R[d] = getbit(op2,15,0) | (getbit(R[n],31,16)<<0x10);
    }
    else{
        R[d] = getbit(R[n],15,0) | (getbit(op2,31,16)<<0x10);
    }
}

void mul(uint32_t *R,ui d,ui n,ui m){  return _mul(R,0,d,n,m);}
void mulS(uint32_t *R,ui d,ui n,ui m){ return _mul(R,1,d,n,m);}
void pkh_lsl(uint32_t*R,ui d,ui n,ui m,ui shift_n){return pkh(R,0,d,n,m,armo_lsl,shift_n);}
void pkh_asr(uint32_t*R,ui d,ui n,ui m,ui shift_n){return pkh(R,1,d,n,m,armo_asr,shift_n);}

static int64_t SignedSatQ_32(ui *q,int64_t v,ui n){
    int64_t min = -(1<<(n-1));
    int64_t max = (1<<(n-1))-1;
    if(v<min){
        if(q)*q = 1;
        return min;
    }
    else if(v>max){
        if(q)*q = 1;
        return max;
    }
    if(q)*q = 0;
    return v;
}

static uint32_t UnsignedSatQ_32(int32_t *q,int64_t v,ui n){
    int64_t max = (1<<(n))-1;
    if(v<0){
        if(q)*q = 1;
        return 0;
    }
    else if(v>max){
        if(q)*q = 1;
        return 0xffffffff;
    }
    if(q)*q = 0;
    return v;
}

static int32_t SignedSatQ(int32_t *q,int32_t v,ui n){
    int32_t min = 0-(1<<(n-1));
    int32_t max = (1<<(n-1))-1;
    if(v<min){
        if(q)*q = 1;
        return min;
    }
    else if(v>max){
        if(q)*q = 1;
        return max;
    }
    if(q)*q = 0;
    return v;
}

static int32_t SignedSat(uint32_t v,ui n){
    return SignedSatQ(0,v,n);
}

static int32_t UnsignedSatQ(int32_t *q,int32_t v,ui n){
    int32_t max = (1<<n) - 1;
    if(v>max){
        if(q)*q = 1;
        return max;
    }
    else if(v<0){
        if(q)*q = 1;
        return 0;
    }
    if(q)*q = 0;
    return getbit(v,n-1,0);
}

static int32_t UnsignedSat(int32_t v,ui n){
    return UnsignedSatQ(0,v,n);
}

void qadd(int32_t*R,ui d,ui n,ui m){
    int64_t sum1 = (int64_t)R[n]+(int64_t)R[m];
    R[d] = SignedSatQ_32(0,sum1,32);
}

void qadd16(int32_t*R,ui d,ui n,ui m){
    int32_t sum1 = getbits(R[n],15,0 ) + getbits(R[m],15,0 );
    int32_t sum2 = getbits(R[n],31,16) + getbits(R[m],31,16);
    R[d] = SignedSat(sum1,16) | (SignedSat(sum2,16)<<0x10);
}

void qadd8(int32_t*R,ui d,ui n,ui m){
    #if !FASTSAT
    int32_t sum1 = getbits(R[n], 7,0 ) + getbits(R[m], 7,0 );
    int32_t sum2 = getbits(R[n],15,8) +  getbits(R[m],15,8);
    int32_t sum3 = getbits(R[n],23,16) + getbits(R[m],23,16);
    int32_t sum4 = getbits(R[n],31,24) + getbits(R[m],31,24);

    R[d] =  (SignedSat(sum1,8)&0xff)         |  ((SignedSat(sum2,8)&0xff)<<0x8) |
           ((SignedSat(sum3,8)&0xff)<<0x10) |  ((SignedSat(sum4,8)&0xff)<<0x18);
    #else
    uint32_t op1 = R[n];
    uint32_t op2 = R[m];
    /*
    数的取值分3种情况
    负数与负数相加,如果结果是正数,则溢出,小于-128
    正数与正数相加,如果结果为负数,则溢出,大于127
    正数与负数相加,范围一直是{127,-128}

    可以参考以下推导式

    s为符号值
    id  op1 o op2
    A.    0 ^ 1    = 1,        负数与正数相加,不溢出
    B.    1 ^ 0    = 1,        正数与负数相加,不溢出
    C.    1 ^ 1    = 0,        负数与负数相加,可能溢出, 如结果为正数则溢出
    D.    0 ^ 0    = 0,        正数与正数相加,可能溢出, 如结果为负数则溢出

    为C,D添加一个下一个推导式
    (1^1) | (sum^0)     ,这里sum为结果,必须为1,否则溢出,所以结果必须为负数。这时变成 (0) | (1^0) 和A,B公式相等
    (0^0) | (sum^1)     ,sum必须为正数,这样才能匹配 (0)|(0^1)

    所以公式应该是
    (s^s)|(sum^~s)
     0^0 |   0^~0   = 0|1 = 1    正数与正数相加,得到结果为正数,没有溢出
     0^0 |   1^~0   = 0|0 = 0    正数与正数相加,得到结果为负数,溢出
     1^1 |   0^~1   = 0|0 = 0    负数与负数相加,得到结果为正数,溢出
     1^1 |   1^~1   = 0|1 = 1    负数与负数相加,得到结果为负数,没有溢出
     1^0     ...    = 1|x = 1    直接不存在溢出
     0^1     ...    = 1|x = 1    不存在溢出
    */
    uint32_t op1h = op1 & 0x80808080;
    uint32_t op2h = op2 & 0x80808080;
    uint32_t sum_mask = (op1^op2);

    //低位相加
    uint32_t sumlo = (op1&~0x80808080) + (op2&~0x80808080);

    //每8位的符号位
    uint32_t sumhi = (op1h+op2h+(sumlo&0x80808080))&0x80808080;
    /*结果*/
    uint32_t sum = sumhi | (sumlo&~0x80808080);

    /* s^s   |= sum^~s */
    sum_mask |= sumhi^(~sum_mask&0x80808080);

    /*已经计算出溢出值,如果有溢出,则把符号值全去掉*/
    sum &= ~sum_mask;
    /*
    如果没有溢出则为1
    溢出为0,
    把他们取反,
    变成溢出时为1,不溢出则为0

    如果溢出则变成0x7f
    否则为0x0
    如果溢出时,并且为负数时,需要+1
    */
    sum_mask = ~sum_mask & 0x80808080;
    sum_mask >>= 7;
    sum_mask *= 0x7f;

    sum |= sum_mask;

    /*
    需要0x01+0x7f变成0x80,只保存溢出标志
    */
    sum_mask&=0x01010101;

    /*
    一般,溢出时,op1和op2的符号位是相同的,所以取op1或者op2都行
    如果为正数,则 sum_mask&=op1h 为0
    如果为负数,则 sum_mask&=op1h 为1
        注意此时sum_mask已经判断了是否存在溢出,如果不溢出,则sum_mask一直为0
    */
    op1h >>= 7;
    sum_mask &= op1h;
    sum += sum_mask;
    R[d] = sum;

    #endif
}

void qasx(int32_t*R,ui d,ui n,ui m){
    int32_t diff = getbits(R[n],15,0) - getbits(R[m],31,16);
    int32_t sum =  getbits(R[n],31,16) + getbits(R[m],15,0);
    R[d] = SignedSat(diff,16) | (SignedSat(sum,16)<<0x10);
}

void qdadd(int32_t*R,ui d,ui n,ui m){
    ui sat1,sat2;
    int64_t doubled = SignedSatQ_32(&sat1,(int64_t)R[n] * 2,32);
    R[d] = SignedSatQ_32(&sat2,(int64_t)R[m]+doubled,32);
    if(sat1||sat2){
        R[arm_qflag] = 1;
    }
}

void qdsub(int32_t*R,ui d,ui n,ui m){
    ui sat1,sat2;
    int64_t doubled = SignedSatQ_32(&sat1,(int64_t)R[n] * 2,32);
    R[d] = SignedSatQ_32(&sat2,(int64_t)R[m]-doubled,32);
    if(sat1||sat2){
        R[arm_qflag] = 1;
    }
}

void qsax(int32_t*R,ui d,ui n,ui m){
    int32_t sum = getbits(R[n],15,0) + getbits(R[m],31,16);
    int32_t diff =  getbits(R[n],31,16) - getbits(R[m],15,0);
    R[d] = SignedSat(sum,16) | (SignedSat(diff,16)<<0x10);
}

void qsub(int32_t*R,ui d,ui n,ui m){
    int64_t diff = (int64_t)R[n]-(int64_t)R[m];
    R[d] = SignedSatQ_32(0,diff,32);
}

void qsub16(int32_t*R,ui d,ui n,ui m){
    int32_t diff1 = getbits(R[n],15,0 ) - getbits(R[m],15,0 );
    int32_t diff2 = getbits(R[n],31,16) - getbits(R[m],31,16);
    R[d] = SignedSat(diff1,16) | (SignedSat(diff2,16)<<0x10);
}

void qsub8(int32_t*R,ui d,ui n,ui m){
    int32_t diff1 = getbits(R[n], 7,0 ) - getbits(R[m], 7,0 );
    int32_t diff2 = getbits(R[n],15,8)  - getbits(R[m],15,8);
    int32_t diff3 = getbits(R[n],23,16) - getbits(R[m],23,16);
    int32_t diff4 = getbits(R[n],31,24) - getbits(R[m],31,24);

    R[d] =  (SignedSat(diff1,8)&0xff)         |  ((SignedSat(diff2,8)&0xff)<<0x8) |
           ((SignedSat(diff3,8)&0xff)<<0x10) |  ((SignedSat(diff4,8)&0xff)<<0x18);
}

void rbit(uint32_t*R,ui d,ui m){
    uint32_t rm = R[m];
    uint32_t rd = 0;
    ui i;
    for(i=0;i<32;i++){
        rd |= ((rm>>i)&1)<<(31-i);
    }
    R[d] = rd;
}

void rev(uint32_t*R,ui d,ui m){
    R[d] =  (getbit(R[m],7,0)<<0x18)   | (getbit(R[m],15,8)<<0x10) |
            (getbit(R[m],23,16)<<0x08) | (getbit(R[m],31,24)<<0x00);
}

void rev16(uint32_t*R,ui d,ui m){
    R[d] =  (getbit(R[m],7,0)<<0x8)   | (getbit(R[m],15,8)<<0x0) |
            (getbit(R[m],23,16)<<0x18) | (getbit(R[m],31,24)<<0x10);
}

void revsh(uint32_t*R,ui d,ui m){
    R[d] = getbit(R[m],15,8)|(getbits(R[m],7,0)<<8);
}

void sadd16(int32_t*R,ui d,ui n,ui m){
    int32_t sum1 = getbits(R[n],15, 0) + getbits(R[m],15, 0);
    int32_t sum2 = getbits(R[n],31,16) + getbits(R[m],31,16);
    R[d] = getbit(sum1,15,0) | (sum2<<0x10);
    R[arm_ge] = (sum1>=0?0b11:0b00)|(sum2>=0?0b1100:0b0000);
}

void sadd8(int32_t*R,ui d,ui n,ui m){
    int32_t sum1 = getbits(R[n],07, 0) + getbits(R[m],07, 0);
    int32_t sum2 = getbits(R[n],15, 8) + getbits(R[m],15, 8);
    int32_t sum3 = getbits(R[n],23,16) + getbits(R[m],23,16);
    int32_t sum4 = getbits(R[n],31,24) + getbits(R[m],31,24);
    R[d] = (getbit(sum1,7,0)&0xff) | ((getbit(sum2,7,0)&0xff)<<0x8) |
        ((getbit(sum3,7,0)&0xff)<<0x10) | ((getbit(sum4,7,0)&0xff)<<0x18);
    R[arm_ge] = (sum1>=0?0b1:0b00)|(sum2>=0?0b10:0b0000)|
                (sum3>=0?0b100:0b00)|(sum4>=0?0b1000:0b00);
}

void sasx(int32_t*R,ui d,ui n,ui m){
    int32_t diff = getbits(R[n],15,0) - getbits(R[m],31,16);
    int32_t sum =  getbits(R[n],31,16) + getbits(R[m],15,0);
    R[d] = getbit(diff,15,0) | (sum<<0x10);
    R[arm_ge] = (diff>=0?0b11:0b00)|(sum>=0?0b1100:0b0000);
}

void shadd16(int32_t*R,ui d,ui n,ui m){
    int32_t sum1 = getbits(R[n],15,0 ) + getbits(R[m],15,0 );
    int32_t sum2 = getbits(R[n],31,16) + getbits(R[m],31,16);
    R[d] = getbit(sum1,16,1) | (getbit(sum2,16,1)<<0x10);
}


void shadd8(int32_t*R,ui d,ui n,ui m){
    int32_t sum1 = getbits(R[n], 7,0 ) + getbits(R[m], 7,0 );
    int32_t sum2 = getbits(R[n],15,8) +  getbits(R[m],15,8);
    int32_t sum3 = getbits(R[n],23,16) + getbits(R[m],23,16);
    int32_t sum4 = getbits(R[n],31,24) + getbits(R[m],31,24);

    R[d] =  getbit(sum1,8,1) | (getbit(sum2,8,1)<<0x8) |
            (getbit(sum3,8,1)<<0x10) | (getbit(sum4,8,1)<<0x18);
}

void shasx(int32_t*R,ui d,ui n,ui m){
    int32_t diff = getbits(R[n],15,0) - getbits(R[m],31,16);
    int32_t sum =  getbits(R[n],31,16) + getbits(R[m],15,0);
    R[d] = getbit(diff,16,1) | (getbit(sum,16,1)<<0x10);
}

void shsax(int32_t*R,ui d,ui n,ui m){
    int32_t sum = getbits(R[n],15,0) + getbits(R[m],31,16);
    int32_t diff =  getbits(R[n],31,16) - getbits(R[m],15,0);
    R[d] = getbit(sum,16,1) | (getbit(diff,16,1)<<0x10);
}

void shsub16(int32_t*R,ui d,ui n,ui m){
    int32_t diff1 = getbits(R[n],15,0 ) - getbits(R[m],15,0 );
    int32_t diff2 = getbits(R[n],31,16) - getbits(R[m],31,16);
    R[d] = getbit(diff1,16,1) | (getbit(diff2,16,1)<<0x10);
}

void shsub8(int32_t*R,ui d,ui n,ui m){
    int32_t diff1 = getbits(R[n], 7,0 ) - getbits(R[m], 7,0 );
    int32_t diff2 = getbits(R[n],15,8)  - getbits(R[m],15,8);
    int32_t diff3 = getbits(R[n],23,16) - getbits(R[m],23,16);
    int32_t diff4 = getbits(R[n],31,24) - getbits(R[m],31,24);

    R[d] =  getbit(diff1,8,1) | (getbit(diff2,8,1)<<0x8) |
        (getbit(diff3,8,1)<<0x10) | (getbit(diff4,8,1)<<0x18);
}

static void _smla(int32_t*R,ui d,ui n,ui m,ui a,ui n_high,ui m_high){
    int32_t op1 = n_high?getbits(R[n],31,16):getbits(R[n],15,0);
    int32_t op2 = m_high?getbits(R[m],31,16):getbits(R[m],15,0);
    int64_t result = (int64_t)op1 * (int64_t)op2 + (int64_t)R[a];
    R[d] = result&0xffffffff;
    if(result!=R[d]){
        R[arm_qflag] = 1;
    }
}

void smla(int32_t*R,ui d,ui n,ui m,ui a)    {_smla(R,d,n,m,a,0,0);};
void smla_nH(int32_t*R,ui d,ui n,ui m,ui a) {_smla(R,d,n,m,a,1,0);};
void smla_mH(int32_t*R,ui d,ui n,ui m,ui a) {_smla(R,d,n,m,a,0,1);};
void smla_nmH(int32_t*R,ui d,ui n,ui m,ui a){_smla(R,d,n,m,a,1,1);};

void smlax(int32_t*R,ui d,ui n,ui m,ui a){smla_nH(R,d,n,m,a);}
void smlay(int32_t*R,ui d,ui n,ui m,ui a){smla_mH(R,d,n,m,a);}
void smlaxy(int32_t*R,ui d,ui n,ui m,ui a){smla_nmH(R,d,n,m,a);}

static void _smld(int32_t*R,ui d,ui n,ui m,ui a,ui m_swap){
    int32_t pro1,pro2;
    pro1 = getbits(R[n],15,0)  * m_swap?getbits(R[m],31,16):getbits(R[m],15,0);
    pro2 = getbits(R[n],31,16) * m_swap?getbits(R[m],15,0): getbits(R[m],31,16);
    int64_t result = (int64_t)pro1+(int64_t)pro2+(int64_t)R[a];
    R[d] = result&0xffffffff;
    if(result!=R[d]){
        R[arm_qflag] = 1;
    }
}

void smld_swap(int32_t*R,ui d,ui n,ui m,ui a){_smld(R,d,n,m,a,1);}
void smldx(int32_t*R,ui d,ui n,ui m,ui a){_smld(R,d,n,m,a,1);}
void smld     (int32_t*R,ui d,ui n,ui m,ui a){_smld(R,d,n,m,a,0);}
static void _smlal(int32_t*R,ui dHi,ui dLo,ui n,ui m,ui S){
    int64_t result = (int64_t)R[dHi]<<32 | R[dLo];
    result += R[n] * R[m];
    R[dHi] = result>>0x20;
    R[dLo] = (uint32_t)result;
    if(S){
        R[arm_nflag] = result<0?1:0;
        R[arm_zflag] = result==0?1:0;
    }
}

void smlal(uint32_t*R,ui dLo,ui dHi,ui n,ui m){ _smlal((int32_t*)R,dHi,dLo,n,m,0);};
void smlalS(uint32_t*R,ui dLo,ui dHi,ui n,ui m){_smlal((int32_t*)R,dHi,dLo,n,m,1);};

static void _smlal_xy(int32_t*R,ui dHi,ui dLo,ui n,ui m,ui n_high,ui m_high){
    int32_t op1 = n_high?getbits(R[n],31,16):getbits(R[n],15,0);
    int32_t op2 = m_high?getbits(R[m],31,16):getbits(R[m],15,0);
    int64_t result = ((int64_t)R[dHi]<<0x20) | R[dLo];
    result += (int64_t)op1 * (int64_t)op2;
    R[dLo] = result&0xffffffff;
    R[dHi] = result>>32;
}

void smlalx(int32_t*R,ui dLo,ui dHi,ui n,ui m){_smlal_xy(R,dHi,dLo,n,m,1,0);}
void smlaly(int32_t*R,ui dLo,ui dHi,ui n,ui m){_smlal_xy(R,dHi,dLo,n,m,0,1);}
void smlalxy(int32_t*R,ui dLo,ui dHi,ui n,ui m){_smlal_xy(R,dHi,dLo,n,m,1,1);}

static void _smlald_(int32_t*R,ui dLo,ui dHi,ui n,ui m,ui m_swap){
    int32_t op2 = m_swap?ror(R[m],16):R[m];
    int32_t p1 = (int16_t)R[n] * (int16_t)op2;
    int32_t p2 = (int16_t)(R[n]>>16) * (int16_t)(op2>>16);
    int64_t rd = (int64_t)R[dHi]<<32 | (int64_t)R[dLo];
    int64_t result = p1 + p2 + rd;
    R[dHi] = result>>32;
    R[dLo] = result&(~0);
}

void smlald(int32_t*R,ui dLo,ui dHi,ui n,ui m){_smlald_(R,dLo,dHi,n,m,0);};
void smlaldx(int32_t*R,ui dLo,ui dHi,ui n,ui m){_smlald_(R,dLo,dHi,n,m,1);};

#if 0
//应该是写错了
static void _smlad(int32_t*R,ui dHi,ui dLo,ui n,ui m,ui m_swap){
    int32_t pro1,pro2;
    pro1 = getbits(R[n],15,0)  * m_swap?getbits(R[m],31,16):getbits(R[m],15,0);
    pro2 = getbits(R[n],31,16) * m_swap?getbits(R[m],15,0): getbits(R[m],31,16);
    int64_t result = ((int64_t)R[dHi]<<32) | R[dLo];
    result += (int64_t)pro1+(int64_t)pro2;
    R[dLo] = result&0xffffffff;
    R[dHi] = result>>0x20;
}

void smlad(int32_t*R,ui dHi,ui dLo,ui n,ui m){_smlad(R,dHi,dLo,n,m,0);}
void smlad_swap(int32_t*R,ui dHi,ui dLo,ui n,ui m){_smlad(R,dHi,dLo,n,m,1);}
#else
static void _smlad(int32_t *R,ui d,ui a,ui n,ui m,int m_swap){
    uint32_t operand2;
    if(m_swap){
        operand2 = ror(R[m],16);
    }
    else{
        operand2 = R[m];
    }
    int32_t product1 = bit(R[n],0,16)  * bit(operand2,0,16);
    int32_t product2 = bit(R[n],16,16) * bit(operand2,16,16);
    uint64_t reuslt = (u64)product1 + (u64)product2 + (u64)R[a];
    R[d] = reuslt & 0xffffffff;
    if(R[d]!=reuslt){
        R[arm_qflag] = 1;
    }
}

void smlad(int32_t*R,ui d,ui a,ui n,ui m){_smlad(R,d,a,n,m,0);}
void smlad_swap(int32_t*R,ui d,ui a,ui n,ui m){_smlad(R,d,a,n,m,1);}
void smladx(int32_t*R,ui d,ui a,ui n,ui m){_smlad(R,d,a,n,m,1);}

#endif
static void _smlaw_y(int32_t*R,ui d,ui n,ui m,ui a,ui m_high){
    int64_t result = (int64_t)R[n] * (m_high?(int64_t)getbits(R[m],31,16):(int64_t)getbits(R[m],15,0)) + ((int64_t)R[a]<<16);
    R[d] = result>>0x10;
    if(result>>0x10!=R[d]){
        R[arm_qflag] = 1;
    }
}

static void smlaw(int32_t*R,ui d,ui n,ui m,ui a){ _smlaw_y(R,d,n,m,a,0);}
static void smlawy(int32_t*R,ui d,ui n,ui m,ui a){ _smlaw_y(R,d,n,m,a,1);}

static void _smlsd_x(int32_t*R,ui d,ui n,ui m,ui a,ui m_high){
    int64_t pro1,pro2;
    pro1 = (int64_t)getbits(R[n],15,0) *  m_high?(int64_t)getbits(R[m],31,16):(int64_t)getbits(R[m],15,0);
    pro1 = (int64_t)getbits(R[n],31,16) * m_high?(int64_t)getbits(R[m],15,0):(int64_t)getbits(R[m],31,16);
    int64_t result = pro1 - pro2 + R[a];
    R[d] = (int32_t)result;
    if(result!=R[d]){
        R[arm_qflag] = 1;
    }
}

void smlsd(int32_t*R, ui d,ui n,ui m,ui a){_smlsd_x(R,d,n,m,a,0);}
void smlsdx(int32_t*R,ui d,ui n,ui m,ui a){_smlsd_x(R,d,n,m,a,1);}

static void _smlsld(int32_t*R,ui dHi,ui dLo,ui n,ui m,ui m_swap){
    int64_t pro1,pro2;
    pro1 = (int64_t)getbits(R[n],15,0)  * m_swap?(int64_t)getbits(R[n],31,16):(int64_t)getbits(R[n],15,0);
    pro1 = (int64_t)getbits(R[n],31,16) * (!m_swap?(int64_t)getbits(R[n],31,16):(int64_t)getbits(R[n],15,0));
    int64_t result = (int64_t)((int64_t)R[dHi]<<32) | R[dLo];
    result = pro1 - pro2 + result;
    R[dHi] = result>>32;
    R[dLo] = (int32_t)result;
}

void smlsld (int32_t*R,ui dHi,ui dLo,ui n,ui m){ _smlsld(R,dHi,dLo,n,m,0);}
void smlsldx(int32_t*R,ui dHi,ui dLo,ui n,ui m){ _smlsld(R,dHi,dLo,n,m,1);}

static void _smmla(int32_t*R,ui d,ui n,ui m,ui a,ui round){
    int64_t result = ((int64_t)R[a] << 32) + (int64_t)R[n] * (int64_t)R[m];
    if(round){
        result += 0x80000000;
    }
    R[d] = result>>32;
}

static void _smmls(int32_t*R,ui d,ui n,ui m,ui a,ui round){
    int64_t result = ((int64_t)R[a] << 32) - (int64_t)R[n] * (int64_t)R[m];
    if(round){
        result += 0x80000000;
    }
    R[d] = result>>32;
}

static void _smmul(int32_t*R,ui d,ui n,ui m,ui round){
    int64_t result = (int64_t)R[n] * (int64_t)R[m];
    if(round){
        result += 0x80000000;
    }
    R[d] = result>>32;
}

static void _smuad(int32_t*R,ui d,ui n,ui m,ui m_swap){
    int64_t pro1,pro2;
    pro1 = getbits(R[n],15,0) * m_swap?getbits(R[m],31,16):getbits(R[m],15,0);
    pro2 = getbits(R[n],31,16) * (!m_swap?getbits(R[m],31,16):getbits(R[m],15,0));
    int64_t result = pro1+pro2;
    R[d] = (uint32_t)result;
    if(result!=R[d]){
        R[arm_qflag] = 1;
    }
}

static void _smul(int32_t*uR,ui d,ui n,ui m,ui n_high,ui m_high){
    int32_t *R = (int32_t*)uR;
    int32_t op1 = n_high?getbits(R[n],31,16):getbits(R[n],15,0);
    int32_t op2 = m_high?getbits(R[m],31,16):getbits(R[m],15,0);
    R[d] = op1 * op2;
}

static void _smull(int32_t*R,ui dHi,ui dLo,ui n,ui m,ui S){
    int64_t result = R[n] * R[m];
    R[dHi] = result>>32;
    R[dLo] = (int32_t)result;
    if(S){
        R[arm_nflag] = result<0?1:0;
        R[arm_zflag] = result==0?1:0;
    }
}

static void _smulw(int32_t*R,ui d,ui n,ui m,ui m_high){
    int32_t op2 = m_high?getbits(R[m],31,16):getbits(R[m],15,0);
    uint64_t pro = (int64_t)R[n] * (int64_t)op2;
    R[d] = pro>>16;
}

static void _smusd(int32_t*R,ui d,ui m,ui n,ui m_swap){
    int64_t pro1,pro2;
    pro1 = getbits(R[n],15, 0) * ( m_swap?getbits(R[m],31,16):getbits(R[m],15,0));
    pro2 = getbits(R[n],31,16) * (!m_swap?getbits(R[m],31,16):getbits(R[m],15,0));
    int64_t result = pro1 - pro2;
    R[d] = (int32_t)result;
}

void smmla (uint32_t*R,ui d,ui n,ui m,ui a){ _smmla((int32_t*)R,d,n,m,a,0);}
void smmlaR(uint32_t*R,ui d,ui n,ui m,ui a){ _smmla((int32_t*)R,d,n,m,a,1);}
void smmls (uint32_t*R,ui d,ui n,ui m,ui a){ _smmls((int32_t*)R,d,n,m,a,0);}
void smmlsR(uint32_t*R,ui d,ui n,ui m,ui a){ _smmls((int32_t*)R,d,n,m,a,1);}
void smmul (uint32_t*R,ui d,ui n,ui m,ui a){ _smmul((int32_t*)R,d,n,m,0);}
void smmulR(uint32_t*R,ui d,ui n,ui m,ui a){ _smmul((int32_t*)R,d,n,m,1);}
void smuad (uint32_t*R,ui d,ui n,ui m) {_smuad((int32_t*)R,d,n,m,0);};
void smuadX(uint32_t*R,ui d,ui n,ui m) {_smuad((int32_t*)R,d,n,m,1);};
void smul  (uint32_t*R,ui d,ui n,ui m) {_smul((int32_t*)R,d,n,m,0,0);}
void smulx (uint32_t*R,ui d,ui n,ui m) {_smul((int32_t*)R,d,n,m,1,0);}
void smuly (uint32_t*R,ui d,ui n,ui m) {_smul((int32_t*)R,d,n,m,0,1);}
void smulxy(uint32_t*R,ui d,ui n,ui m) {_smul((int32_t*)R,d,n,m,1,1);}
void smull (uint32_t*R,ui dLo,ui dHi,ui n,ui m) {_smull((int32_t*)R,dHi,dLo,n,m,0);}
void smullS(uint32_t*R,ui dLo,ui dHi,ui n,ui m) {_smull((int32_t*)R,dHi,dLo,n,m,1);}
void smulw (uint32_t*R,ui d,ui n,ui m){ _smulw((int32_t*)R,d,n,m,0);}
void smulwy(uint32_t*R,ui d,ui n,ui m){ _smulw((int32_t*)R,d,n,m,1);}
void smusd (uint32_t*R,ui d,ui m,ui n) {_smusd((int32_t*)R,d,m,n,0);}
void smusdx(uint32_t*R,ui d,ui m,ui n) {_smusd((int32_t*)R,d,m,n,1);}

static void _ssat(int32_t*R,ui d,ui n,ui shift_t,ui shift_n,ui saturate_to){
    int64_t result;
    ui sat;
    int32_t op = Shift(R[n],shift_t,shift_n);
    result = SignedSatQ_32(&sat,op,saturate_to);
    R[d] = result;
    if(sat){
        R[arm_qflag] = 1;
    }
}

static void _ssat16(int32_t*R,ui d,ui n,ui saturate_to){
    int32_t result1,sat1,result2,sat2;
    result1 = SignedSatQ(&sat1,getbits(R[n],15,0),saturate_to);
    result2 = SignedSatQ(&sat2,getbits(R[n],31,16),saturate_to);
    R[d] = getbit(result1,15,0) | (getbit(result2,15,0)<<0x10);
    if(sat1||sat2){
        R[arm_qflag] = 1;
    }
}

void ssat_lsl(int32_t*R,ui d,ui n,ui shift_n,ui saturate_to) {_ssat(R,d,n,armo_lsl,shift_n,saturate_to);}
void ssat_asr(int32_t*R,ui d,ui n,ui shift_n,ui saturate_to) {_ssat(R,d,n,armo_asr,shift_n,saturate_to);}
void ssat16  (int32_t*R,ui d,ui n,ui saturate_to){_ssat16(R,d,n,saturate_to);}
void ssax(int32_t*R,ui d,ui n,ui m){
    int32_t sum = getbits(R[n],15,0) + getbits(R[m],31,16);
    int32_t diff = getbits(R[n],31,16) - getbits(R[m],15,0);
    R[d] = getbit(sum,15,0) | (getbit(diff,15,0)<<0x10);
    R[arm_ge] = (sum>=0?0b11:0b00)|(diff>=0?0b1100:0b0000);
}

void ssub16(int32_t*R,ui d,ui n,ui m){
    int32_t diff1 =  getbits(R[n],15,0) -  getbits(R[m],15,0);
    int32_t diff2 = getbits(R[n],31,16) -  getbits(R[m],31,16);
    R[d] = getbit(diff1,15,0) | (getbit(diff2,15,0)<<0x10);
    R[arm_ge] = (diff1>=0?0b11:0b00)|(diff2>=0?0b1100:0b0000);
}

void ssub8(int32_t*R,ui d,ui n,ui m){
    int32_t diff1 =  getbits(R[n],07, 0) -  getbits(R[m],7, 0);
    int32_t diff2 =  getbits(R[n],15, 8) -  getbits(R[m],15, 8);
    int32_t diff3 =  getbits(R[n],23,16) -  getbits(R[m],23,16);
    int32_t diff4 =  getbits(R[n],31,24) -  getbits(R[m],31,24);
    R[d] = getbit(diff1,7,0) | (getbit(diff2,7,0)<<0x8) |
            (getbit(diff3,7,0)<<0x10) | (getbit(diff4,7,0)<<0x18);
    R[arm_ge] = (diff1>=0?0b1:0b00)|(diff2>=0?0b10:0b0000)|
                (diff3>=0?0b100:0b00)|(diff4>=0?0b1000:0b0000);
}

void svc(uint32_t*R,ui imm){
    cpu_svc(R,imm);
}

void swpb(uint32_t*R,ui t,ui t2,ui n){
    uint32_t data = read_u8(R,R[n]);
    write_u8(R,t2,R[n]);
    R[t] = data;
}

void swp(uint32_t*R,ui t,ui t2,ui n){
    uint32_t data = read_u32(R,R[n]);
    write_u32(R,t2,R[n]);
    R[t] = Shift(data,armo_ror,R[n]&0x3);
}

void sxtab(uint32_t*R,ui d,ui n,ui m,ui rotation){
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    R[d] = R[n] + getbits(rot,7,0);
}

void sxtab16(uint32_t*uR,ui d,ui n,ui m,ui rotation){
    int32_t *R = (int32_t*)uR;
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    int32_t op1 = getbit(R[n],15,0)  + getbits(rot,7,0);
    int32_t op2 = getbit(R[n],31,16) + getbits(rot,23,16);
    R[d] = getbit(op1,15,0) | (getbit(op2,15,0)<<0x10);
}

void sxtah(uint32_t*uR,ui d,ui n,ui m,ui rotation){
    int32_t *R = (int32_t*)uR;
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    R[d] = R[n] + getbits(rot,15,0);
}

void sxtb(uint32_t*uR,ui d,ui m,ui rotation){
    int32_t *R = (int32_t*)uR;
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    R[d] = getbits(rot,7,0);
}

void sxtb16(uint32_t*uR,ui d,ui m,ui rotation){
    int32_t *R = (int32_t*)uR;
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    int32_t op1 = getbits(rot,7,0);
    int32_t op2 = getbits(rot,23,16);
    R[d] = getbit(op1,15,0) | (getbit(op2,15,0)<<0x10);
}

void sxth(uint32_t*uR,ui d,ui m,ui rotation){
    int32_t *R = (int32_t*)uR;
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    R[d] = getbits(rot,15,0);
}

#define SXTA_N(name,value) \
    void name##value(uint32_t*R,ui d,ui n,ui m){\
        name(R,d,n,m,value); \
    }

#define SXT_N(name,value) \
    void name##value(uint32_t*R,ui d,ui m){\
        name(R,d,m,value); \
    }

#define SXTA(name) \
SXTA_N(name,0); \
SXTA_N(name,1); \
SXTA_N(name,2); \
SXTA_N(name,3);

#define SXT(name) \
SXT_N(name,0); \
SXT_N(name,1); \
SXT_N(name,2); \
SXT_N(name,3);

SXTA(sxtab  );
SXTA(sxtab16);
SXTA(sxtah );
SXT(sxtb);
SXT(sxtb16);
SXT(sxth);


void uadd16(uint32_t*R,ui d,ui n,ui m){
    uint32_t sum1 = getbit(R[n],15, 0) + getbit(R[m],15, 0);
    uint32_t sum2 = getbit(R[n],31,16) + getbit(R[m],31,16);
    R[d] = getbit(sum1,15,0) | (sum2<<0x10);
    R[arm_ge] = (sum1>=0x10000?0b11:0b00)|(sum2>=0x10000?0b1100:0b0000);
}

void uadd8 (uint32_t*R,ui d,ui n,ui m){
    uint32_t sum1 = getbit(R[n],07, 0) + getbit(R[m],07, 0);
    uint32_t sum2 = getbit(R[n],15, 8) + getbit(R[m],15, 8);
    uint32_t sum3 = getbit(R[n],23,16) + getbit(R[m],23,16);
    uint32_t sum4 = getbit(R[n],31,24) + getbit(R[m],31,24);
    R[d] = (getbit(sum1,7,0)&0xff) | ((getbit(sum2,7,0)&0xff)<<0x8) |
        ((getbit(sum3,7,0)&0xff)<<0x10) | ((getbit(sum4,7,0)&0xff)<<0x18);
    R[arm_ge] = (sum1>=0x100?0b1:0b00)|(sum2>=0x100?0b10:0b0000)|
                (sum3>=0x100?0b100:0b00)|(sum4>=0x100?0b1000:0b00);
}

void uasx(uint32_t*R,ui d,ui n,ui m){
    uint32_t diff = getbit(R[n],15,0) -  getbit(R[m],31,16);
    uint32_t sum =  getbit(R[n],31,16) + getbit(R[m],15,0);
    R[d] = getbit(diff,15,0) | (sum<<0x10);
    R[arm_ge] = (diff>=0x0?0b11:0b00)|(sum>=0x10000?0b1100:0b0000);
}

// void udiv(uint32_t*R,ui d,ui n,ui m){
//     R[d] = R[n]/R[m];
// }

void uhadd16(uint32_t*R,ui d,ui n,ui m){
    uint32_t sum1,sum2;
    sum1 = getbit(R[n],15, 0) + getbit(R[m],15, 0);
    sum2 = getbit(R[n],31, 16) + getbit(R[m],31,16);
    R[d] = sum1>>1 | ((sum2>>1)<<0x10);
}

void uhadd8(uint32_t*R,ui d,ui n,ui m){
    uint32_t sum1 = getbit(R[n],07,  0) + getbit(R[m],07,  0);
    uint32_t sum2 = getbit(R[n],15,  8) + getbit(R[m],15,  8);
    uint32_t sum3 = getbit(R[n],23, 16) + getbit(R[m],23, 16);
    uint32_t sum4 = getbit(R[n],31, 24) + getbit(R[m],31, 24);
    R[d] = sum1>>1 | ((sum2>>1)<<0x8)|
           ((sum3>>1)<<0x10) | ((sum4>>1)<<0x18);
}

void uhasx(uint32_t*R,ui d,ui n,ui m){
    uint32_t sum1,sum2;
    sum1 = getbit(R[n],15, 0)  - getbit(R[m],31,16);
    sum2 = getbit(R[n],31, 16) + getbit(R[m],15, 0);
    R[d] = sum1>>1 | ((sum2>>1)<<0x10);
}

void uhsax(uint32_t*R,ui d,ui n,ui m){
    uint32_t sum1,sum2;
    sum1 = getbit(R[n],15, 0)  + getbit(R[m],31,16);
    sum2 = getbit(R[n],31, 16) - getbit(R[m],15, 0);
    R[d] = sum1>>1 | ((sum2>>1)<<0x10);
}

void uhsub16(uint32_t*R,ui d,ui n,ui m){
    uint32_t sum1,sum2;
    sum1 = getbit(R[n],15, 0)  - getbit(R[m],15, 0);
    sum2 = getbit(R[n],31, 16) - getbit(R[m],31,16);
    R[d] = sum1>>1 | ((sum2>>1)<<0x10);
}

void uhsub8(uint32_t*R,ui d,ui n,ui m){
    uint32_t sum1 = getbit(R[n],07,  0) - getbit(R[m],07,  0);
    uint32_t sum2 = getbit(R[n],15,  8) - getbit(R[m],15,  8);
    uint32_t sum3 = getbit(R[n],23, 16) - getbit(R[m],23, 16);
    uint32_t sum4 = getbit(R[n],31, 24) - getbit(R[m],31, 24);
    R[d] = sum1>>1 | ((sum2>>1)<<0x8)|
           ((sum3>>1)<<0x10) | ((sum4>>1)<<0x18);
}

void umaal(uint32_t*R,ui dHi,ui dLo,ui n,ui m){
    uint64_t result = (uint64_t)R[n] * (uint64_t)R[m] + (uint64_t)R[dHi] + (uint64_t)R[dLo];
    R[dHi] = result>>0x20;
    R[dLo] = result;
}

static void _umlal(uint32_t*R,ui dHi,ui dLo,ui n,ui m,ui S){
    uint64_t result;
    result = (uint64_t)((int64_t)R[dHi]<<0x20) | R[dLo];
    result += (uint64_t)R[n] * (uint64_t)R[m];
    R[dHi] = result>>0x20;
    R[dLo] = result;
    if(S){
        R[arm_nflag] = (int64_t)result <0?1:0;
        R[arm_zflag] = result==0?1:0;
    }
}

static void _umull(uint32_t*R,ui dHi,ui dLo,ui n,ui m,ui S){
    uint64_t result;
    result = (uint64_t)R[n] * (uint64_t)R[m];
    R[dHi] = result>>0x20;
    R[dLo] = result;
    if(S){
        R[arm_nflag] = (int64_t)result <0?1:0;
        R[arm_zflag] = result==0?1:0;
    }
}

void umlal (uint32_t*R,ui dLo,ui dHi,ui n,ui m){_umlal(R,dHi,dLo,n,m,0);}
void umlals(uint32_t*R,ui dLo,ui dHi,ui n,ui m){_umlal(R,dHi,dLo,n,m,1);}
void umull (uint32_t*R,ui dLo,ui dHi,ui n,ui m){_umull(R,dHi,dLo,n,m,0);}
void umulls(uint32_t*R,ui dLo,ui dHi,ui n,ui m){_umull(R,dHi,dLo,n,m,1);}

void uqadd16(uint32_t*R,ui d,ui n,ui m){
    uint32_t sum1 = getbit(R[n],15,0 ) + getbit(R[m],15,0 );
    uint32_t sum2 = getbit(R[n],31,16) + getbit(R[m],31,16);
    R[d] = UnsignedSat(sum1,16) | (UnsignedSat(sum2,16)<<0x10);
}

void uqadd8(uint32_t*R,ui d,ui n,ui m){
    uint32_t sum1 = getbit(R[n], 7,0 ) + getbit(R[m], 7,0 );
    uint32_t sum2 = getbit(R[n],15,8) +  getbit(R[m],15,8);
    uint32_t sum3 = getbit(R[n],23,16) + getbit(R[m],23,16);
    uint32_t sum4 = getbit(R[n],31,24) + getbit(R[m],31,24);

    R[d] =  (UnsignedSat(sum1,8))         |  ((UnsignedSat(sum2,8))<<0x8) |
           ((UnsignedSat(sum3,8))<<0x10) |  ((UnsignedSat(sum4,8) )<<0x18);
}

void uqsub16(uint32_t*R,ui d,ui n,ui m){
    uint32_t diff1 = getbit(R[n],15,0 ) - getbit(R[m],15,0 );
    uint32_t diff2 = getbit(R[n],31,16) - getbit(R[m],31,16);
    R[d] = UnsignedSat(diff1,16) | (UnsignedSat(diff2,16)<<0x10);
}

void uqsub8(uint32_t*R,ui d,ui n,ui m){
    uint32_t diff1 = getbit(R[n], 7,0 ) - getbit(R[m], 7,0 );
    uint32_t diff2 = getbit(R[n],15,8)  - getbit(R[m],15,8);
    uint32_t diff3 = getbit(R[n],23,16) - getbit(R[m],23,16);
    uint32_t diff4 = getbit(R[n],31,24) - getbit(R[m],31,24);

    R[d] =  (UnsignedSat(diff1,8))         |  ((UnsignedSat(diff2,8))<<0x8) |
           ((UnsignedSat(diff3,8))<<0x10) |  ((UnsignedSat(diff4,8))<<0x18);
}

void uqasx(uint32_t*R,ui d,ui n,ui m){
    uint32_t diff = getbit(R[n],15,0) -  getbit(R[m],31,16);
    uint32_t sum =  getbit(R[n],31,16) + getbit(R[m],15,0);
    R[d] = UnsignedSat(diff,16) | (UnsignedSat(sum,16)<<0x10);
}

void uqsax(uint32_t*R,ui d,ui n,ui m){
    uint32_t sum =   getbit(R[n],15,0) +  getbit(R[m],31,16);
    uint32_t diff =  getbit(R[n],31,16) - getbit(R[m],15,0);
    R[d] = UnsignedSat(sum,16) | (UnsignedSat(diff,16)<<0x10);
}

void usad8(int32_t*R,ui d,ui n,ui m){
    int32_t diff1 =  (int32_t)getbit(R[n],07, 0) -  getbit(R[m],7, 0);
    int32_t diff2 =  (int32_t)getbit(R[n],15, 8) -  getbit(R[m],15, 8);
    int32_t diff3 =  (int32_t)getbit(R[n],23,16) -  getbit(R[m],23,16);
    int32_t diff4 =  (int32_t)getbit(R[n],31,24) -  getbit(R[m],31,24);
    diff1 = abs(diff1);
    diff2 = abs(diff2);
    diff3 = abs(diff3);
    diff4 = abs(diff4);
    R[d] = diff1 + diff2+diff3+diff4;
}

void usada8(int32_t*R,ui d,ui n,ui m,ui a){
    int32_t diff1 =  (int32_t)getbit(R[n],07, 0) -  getbit(R[m],7, 0);
    int32_t diff2 =  (int32_t)getbit(R[n],15, 8) -  getbit(R[m],15, 8);
    int32_t diff3 =  (int32_t)getbit(R[n],23,16) -  getbit(R[m],23,16);
    int32_t diff4 =  (int32_t)getbit(R[n],31,24) -  getbit(R[m],31,24);
    diff1 = abs(diff1);
    diff2 = abs(diff2);
    diff3 = abs(diff3);
    diff4 = abs(diff4);
    R[d] = R[n] + diff1 + diff2+diff3+diff4;
}

static void _usat(int32_t*R,ui d,ui n,ui shift_t,ui shift_n,ui saturate_to){
    int64_t result;
    int32_t sat;
    int32_t op = Shift(R[n],shift_t,shift_n);
    result = UnsignedSatQ_32(&sat,op,saturate_to);
    R[d] = result;
    if(sat){
        R[arm_qflag] = 1;
    }
}

static void _usat16(int32_t*R,ui d,ui n,ui saturate_to){
    int32_t result1,sat1,result2,sat2;
    result1 = UnsignedSatQ(&sat1,getbits(R[n],15,0),saturate_to);
    result2 = UnsignedSatQ(&sat2,getbits(R[n],31,16),saturate_to);
    R[d] = getbit(result1,15,0) | (getbit(result2,15,0)<<0x10);
    if(sat1||sat2){
        R[arm_qflag] = 1;
    }
}

void usat_lsl(int32_t*R,ui d,ui n,ui shift_n,ui saturate_to) {_usat(R,d,n,armo_lsl,shift_n,saturate_to);}
void usat_asr(int32_t*R,ui d,ui n,ui shift_n,ui saturate_to) {_usat(R,d,n,armo_asr,shift_n,saturate_to);}
void usat16  (int32_t*R,ui d,ui n,ui saturate_to){_usat16(R,d,n,saturate_to);}

void usub16(uint32_t*R,ui d,ui n,ui m){
    int32_t diff1 =  (int32_t)getbit(R[n],15,0) -   getbit(R[m],15,0);
    int32_t diff2 =  (int32_t)getbit(R[n],31,16) -  getbit(R[m],31,16);
    R[d] = getbit(diff1,15,0) | (getbit(diff2,15,0)<<0x10);
    R[arm_ge] = (diff1>=0?0b11:0b00)|(diff2>=0?0b1100:0b0000);
}

void usub8(uint32_t*R,ui d,ui n,ui m){
    int32_t diff1 =  (int32_t)getbit(R[n],07, 0) -  getbit(R[m],7, 0);
    int32_t diff2 =  (int32_t)getbit(R[n],15, 8) -  getbit(R[m],15, 8);
    int32_t diff3 =  (int32_t)getbit(R[n],23,16) -  getbit(R[m],23,16);
    int32_t diff4 =  (int32_t)getbit(R[n],31,24) -  getbit(R[m],31,24);
    R[d] = getbit(diff1,7,0) | (getbit(diff2,7,0)<<0x8) |
            (getbit(diff3,7,0)<<0x10) | (getbit(diff4,7,0)<<0x18);
    R[arm_ge] = (diff1>=0?0b1:0b00)|(diff2>=0?0b10:0b0000)|
                (diff3>=0?0b100:0b00)|(diff4>=0?0b1000:0b0000);
}

void uxtab(uint32_t*R,ui d,ui n,ui m,ui rotation){
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    R[d] = R[n] + getbit(rot,7,0);
}

void uxtab16(uint32_t*R,ui d,ui n,ui m,ui rotation){
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    int32_t op1 = getbit(R[n],15,0)  + getbit(rot,7,0);
    int32_t op2 = getbit(R[n],31,16) + getbit(rot,23,16);
    R[d] = getbit(op1,15,0) | (getbit(op2,15,0)<<0x10);
}

void uxtah(uint32_t*R,ui d,ui n,ui m,ui rotation){
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    R[d] = R[n] + getbit(rot,15,0);
}

void uxtb(uint32_t*R,ui d,ui m,ui rotation){
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    R[d] = getbit(rot,7,0);
}

void uxtb16(uint32_t*R,ui d,ui m,ui rotation){
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    int32_t op1 = getbit(rot,7,0);
    int32_t op2 = getbit(rot,23,16);
    R[d] = getbit(op1,15,0) | (getbit(op2,15,0)<<0x10);
}

void uxth(uint32_t*R,ui d,ui m,ui rotation){
    int32_t rot = Shift(R[m],armo_ror,rotation<<3);
    R[d] = getbit(rot,15,0);
}

//thumb
void t_adc(uint32_t*R,ui rdn,ui rm)           { adc_lsl1_S(R,rdn,rdn,rm,0);}    //adc rdn,rm
void t_add_imm(uint32_t*R,ui rd,ui rn,ui imm){ add_imm8_S(R,rd,rn,imm);}       //add rd,rn,imm3      ;add rdn,imm8
void t_add(uint32_t*R,ui rd,ui rn,ui rm)     { add_lsl1_S(R,rd,rn,rm,0);}      //add rd,rn,rm        ;add rdn,rm
void t_add_sp(uint32_t*R,ui rd,ui imm8)       { add_imm8(R,rd,arm_sp,imm8<<2);}    //add rd,sp,imm8      ;add sp,sp,imm7
// add rd,sp,rd ; add sp,rm 与 add hd,hn 类似
void t_adr(uint32_t*R, ui rd,ui imm8)         { R[rd] = R[arm_pc]+(imm8<<2);}
void t_and(uint32_t*R,ui rd,ui rm)            { and_lsl1_S(R,rd,rd,rm,0);}
void t_asr_imm(uint32_t*R,ui rd,ui rm,ui imm){ mov_asr1_S(R,rd,0,rm,imm);}
void t_lsl_imm(uint32_t*R,ui rd,ui rm,ui imm){ mov_lsl1_S(R,rd,0,rm,imm);}
void t_lsr_imm(uint32_t*R,ui rd,ui rm,ui imm){ mov_lsr1_S(R,rd,0,rm,imm);}
void t_asr(uint32_t*R,ui rd,ui rm)            { mov_asr2_S(R,rd,0,rd,rm);}
void t_lsl(uint32_t*R,ui rd,ui rm)            { mov_lsl2_S(R,rd,0,rd,rm);}
void t_lsr(uint32_t*R,ui rd,ui rm)            { mov_lsr2_S(R,rd,0,rd,rm);}
void t_ror(uint32_t*R,ui rd,ui rm)            { mov_ror2_S(R,rd,0,rd,rm);}

void t_b    (uint32_t*R,ui imm){ imm<<=(31-10); imm>>=(31-10);               jmp_abs(R,(1|R[arm_pc])+((int32_t)imm<<1));}
void t_beq  (uint32_t*R,ui imm){if( R[arm_zflag])jmp_abs(R,                            (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bne  (uint32_t*R,ui imm){if(!R[arm_zflag])jmp_abs(R,                            (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bcs  (uint32_t*R,ui imm){if( R[arm_cflag])jmp_abs(R,                            (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bcc  (uint32_t*R,ui imm){if(!R[arm_cflag])jmp_abs(R,                            (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bmi  (uint32_t*R,ui imm){if( R[arm_nflag])jmp_abs(R,                            (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bpl  (uint32_t*R,ui imm){if(!R[arm_nflag])jmp_abs(R,                            (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bvs  (uint32_t*R,ui imm){if( R[arm_vflag])jmp_abs(R,                            (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bvc  (uint32_t*R,ui imm){if(!R[arm_vflag])jmp_abs(R,                            (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bhi  (uint32_t*R,ui imm){if( R[arm_cflag]&&R[arm_zflag]==0)jmp_abs(R,           (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bls  (uint32_t*R,ui imm){if(!R[arm_cflag]||R[arm_zflag])jmp_abs(R,              (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bge  (uint32_t*R,ui imm){if( R[arm_nflag]==R[arm_vflag])jmp_abs(R,              (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_blt  (uint32_t*R,ui imm){if( R[arm_nflag]!=R[arm_vflag])jmp_abs(R,              (1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bgt  (uint32_t*R,ui imm){if(!R[arm_zflag]&&R[arm_vflag]==R[arm_nflag])jmp_abs(R,(1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_ble  (uint32_t*R,ui imm){if( R[arm_zflag]||R[arm_vflag]!=R[arm_nflag])jmp_abs(R,(1|R[arm_pc])+((int32_t)(int8_t)imm<<1));}
void t_bkpt (uint32_t*R,ui imm)                {cpu_bkpt(R,imm);}
void t_bic  (uint32_t*R,ui rd,ui rm)          { bic_lsl1_S(R,rd,rd,rm,0);}
void t_blx  (uint32_t*R,ui rm)                 { R[arm_lr] = R[arm_pc] - 2 + 1;jmp_abs(R,R[rm]);}
void t_bx  (uint32_t*R,ui rm)                  {/*R[arm_lr]=R[arm_pc]-2;*/ jmp_abs(R,R[rm]);}
void t_mov_pc(uint32_t*R,ui rm)                {/*R[arm_lr]=R[arm_pc]-2;*/ jmp_abs(R,R[rm]|1);} /*不会更改thumb状态*/
#define dR uint32_t*R
#define dd ui d
#define dn ui n
#define dm ui m
#define dimm ui imm
#define dt ui t
void t_cmn        (dR,dn,dm)      { cmn_lsl1_S(R,0,n,m,0);}
void t_cmp_imm    (dR,dn,dimm)    { cmp_imm8_S(R,0,n,imm);}
void t_cmp        (dR,dn,dm)      { cmp_lsl1_S(R,0,n,m,0);}
void t_eor        (dR,dd,dm)      { eor_lsl1_S(R,d,d,m,0);}
void t_ldm        (dR,dn,ui imm)    {
    uint32_t address = R[n];
    ui i;
    ui wback = 1;
    for(i=0;i<8;i++){
        if(imm&1){
            R[i] = read_u32(R,address);
            address += 4;
        }
        imm>>=1;
    }
    if(wback){
        R[n] = address;
    }
};

void t_stm        (dR,dn,ui imm)    {
    uint32_t address = R[n];
    ui i;
    ui wback = 1;
    for(i=0;i<8;i++){
        if(imm&1){
            //R[i] = read_u32(R,address);
            write_u32(R,R[i],address);
            address += 4;
        }
        imm>>=1;
    }
    if(wback){
        R[n] = address;
    }
};


//ldr rt,[rn,imm]
//ldr rt,[sp,imm]
void t_ldr_imm  (dR,dt,dn,dimm)     { ldr3imm(R,t,n,imm);}
void t_ldr_sp   (dR,dt,dimm)        { ldr3imm(R,t,arm_sp,imm);}
void t_ldr_pc   (dR,dt,dimm)        { ldr3imm(R,t,arm_pc,imm);}
void t_ldr      (dR,dt,dn,dm)       { ldr3_lsl(R,t,n,m,0);}
void t_ldrb_imm (dR,dt,dn,dimm)     { ldrb3imm(R,t,n,imm);}
void t_ldrb     (dR,dt,dn,dm)       { ldrb3_lsl(R,t,n,m,0);}
void t_ldrh_imm (dR,dt,dn,dimm)     { ldrh3_imm(R,t,n,imm>>4,imm&0xf);}
void t_ldrh     (dR,dt,dn,dm)       { ldrh3_reg(R,t,n,m);}
void t_ldrsb    (dR,dt,dn,dm)       { ldrsb3_reg(R,t,n,m);}
void t_ldrsh    (dR,dt,dn,dm)       { ldrsh3_reg(R,t,n,m);}

void t_mov_imm  (dR,dd,dimm)        { mov_imm8(R,d,0,imm);}
void t_mov      (dR,dd,dm)          { mov_lsl1(R,d,0,m,0);}
void t_mul      (dR,dd,dm)          { mulS(R,d,d,m); }
void t_mvn      (dR,dd,dm)          { mvn_lsl1_S(R,d,0,m,0);}
void t_neg      (dR,dd,dm)          { /*rsb_lsl1_S(R,d,0,m,0);*/rsb_imm8_S(R,d,m,0);}
void t_orr      (dR,dd,dm)          { orr_lsl1_S(R,d,d,m,0);}
void t_pop      (dR,dimm,ui P){
    uint32_t address = R[arm_sp];
    ui i;
    ui wback = 1;
    for(i=0;i<8;i++){
        if(imm&1){
            R[i] = read_u32(R,address);
            address += 4;
        }
        imm>>=1;
    }
    if(P){
        uint32_t pc = read_u32(R,address);
        address += 4;
        jmp_abs(R,pc);
    }
    if(wback){
        R[arm_sp] = address;
    }
}

void t_push (dR,dimm,ui M){
    uint32_t address = R[arm_sp];
    ui i;
    ui wback = 1;

    if(M){
        address -= 4;
        write_u32(R,R[arm_lr],address);
    }
    for(i=0;i<8;i++){
        if(imm&(1<<7)){
            address -= 4;
            write_u32(R,R[7-i],address);
        }
        imm<<=1;
    }

    if(wback){
        R[arm_sp] = address;
    }
}

void t_rev     (dR,dd,dm)       {rev(R,d,m);}
void t_rev16   (dR,dd,dm)       {rev16(R,d,m);}
void t_revsh   (dR,dd,dm)       {revsh(R,d,m);}
void t_rsb     (dR,dd,dn)       {rsb_imm8_S(R,d,n,0);}
void t_sbc     (dR,dd,dm)       {sbc_lsl1_S(R,d,d,m,0);}
void t_str_imm (dR,dt,dn,dimm)  {str3imm(R,t,n,imm);}              //str rt,[rn,imm]
void t_str_sp  (dR,dt,dimm)     {str3imm(R,t,arm_sp,imm);}      //str rt,[sp,imm]
void t_str     (dR,dt,dn,dm)    {str3_lsl(R,t,n,m,0);}             //str rt,[rn,imm]
void t_strb_imm(dR,dt,dn,dimm)  {strb3imm(R,t,n,imm);}             //strb rt,[rn,imm]
void t_strb    (dR,dt,dn,dm)    {strb3_lsl(R,t,n,m,0);}            //strb rt,[rn,imm]
void t_strh_imm(dR,dt,dn,dimm)  {strh3_imm(R,t,n,imm>>4,imm&0xf);}            //strh rt,[rn,imm]
void t_strh    (dR,dt,dn,dm)    {strh3_reg(R,t,n,m);}              //strh rt,[rn,imm]
void t_sub_imm (dR,dd,dn,dimm)  {sub_imm8_S(R,d,n,imm);}
void t_sub_imm8(dR,dd,dimm)     {sub_imm8_S(R,d,d,imm);}
void t_sub     (dR,dd,dn,dm)    {sub_lsl1_S(R,d,n,m,0);}
void t_sub_sp  (dR,dimm)        {
                                    //sub_imm8(R,arm_sp,arm_sp,imm);
                                    //sub_imm12(R,arm_sp,arm_sp,imm);
                                    sub_imm_ror(R,arm_sp,arm_sp,imm,16-1);
                                } //不会影响状态寄存器
void t_svc     (dR,dimm)        {cpu_svc(R,imm);}
void t_tst     (dR,dn,dm)       {tst_lsl1_S(R,0,n,m,0);}

/*
当
asr,
lsr,
    的imm为0时，imm需要赋值32
*/

void t_asr_imm_zero(uint32_t*R,ui rd,ui rm){ mov_asr1_S(R,rd,0,rm,32);}
void t_lsr_imm_zero(uint32_t*R,ui rd,ui rm){ mov_lsr1_S(R,rd,0,rm,32);}

void t_bl(uint32_t*R,ui imm){
    //uint32_t insn = read_u32(R,R[arm_pc]-4);
    uint16_t insn1 = read_u16(R,R[arm_pc]-4);
    uint16_t insn2 = read_u16(R,R[arm_pc]-2);
    ui J1 = (insn2 >> 13) &1;
    ui J2 = (insn2 >> 11) &1;
    ui S =  (insn1 >> 10) &1;
    ui I1 = (~(J1 ^ S)) & 1;
    ui I2 = (~(J2 ^ S)) & 1;
    ui imm10 = insn1&0x3ff;
    ui imm11 = insn2&0x7ff;
    int32_t imm32 = 0;
    if(S){
        //imm32 |= 0xFE000000;
        imm32 &= 0;
    }
    imm10 |= I2<<10;
    imm10 |= I1<<11;
    imm10 |= S <<12;
    imm32 = ((imm10<<11) | imm11);
    imm32 <<= 32-(10+11+3);
    imm32 >>= 32-(10+11+3);       //*2
    imm32 <<= 1;

    //ui imm32 = (S<<31)|(I1<<30)|(I2<<29)|((imm10<<11|(imm11))<<1);
    R[arm_lr] = (R[arm_pc]&~1)|1;
    jmp_abs(R,R[arm_pc]+imm32|1);
}

void t_nop(uint32_t*R){

}
void t_sxtb(uint32_t*R){}
void t_sxth(uint32_t*R){}
void t_uxtb(uint32_t*R){}
void t_uxth(uint32_t*R){}

//arm 其他
#define NOMSR_MRS 0
void mrs(uint32_t*R,ui d){
    #if  NOMSR_MRS
    cpu_undefined_instruction(R);
    #else
    uint32_t v = 0;
    v = R[arm_cpsr]&0x1f;
    v |= R[arm_nflag]<<31;
    v |= R[arm_zflag]<<30;
    v |= R[arm_cflag]<<29;
    v |= R[arm_vflag]<<28;
    v |= R[arm_qflag]<<27;
    v |= R[arm_iflag]<<7;
    v |= R[arm_fflag]<<6;
    v |= R[arm_tflag]<<5;
    //    //未完全实现
    R[d] = v;
    #endif
}

void mrs_imm(uint32_t*R,ui imm){
    cpu_undefined_instruction(R);
}

void mrs_spsr(uint32_t*R,ui d){
    #if  NOMSR_MRS
    cpu_undefined_instruction(R);
    #else
    //    //未完全实现
    R[d] = R[arm_spsr];
    #endif
}

//用户模式下的msr
static void _msr(uint32_t*R,uint32_t imm){
    R[arm_nflag] = (imm>>31)&1;
    R[arm_zflag] = (imm>>30)&1;
    R[arm_cflag] = (imm>>29)&1;
    R[arm_vflag] = (imm>>28)&1;
    R[arm_qflag] = (imm>>27)&1;
    R[arm_iflag] = (imm>>7)&1;
    R[arm_fflag] = (imm>>6)&1;
    R[arm_tflag] = (imm>>5)&1;
    R[arm_cpsr] = imm;
}

static void _switch_mode(uint32_t*R,uint32_t mode){
    uint8_t oldmode = R[arm_mode];
    R[arm_mode] = mode;
    if(oldmode!=mode){
        switch (oldmode)
        {
        case arm_mode_fiq:{
            R[arm_fiq_r13] = R[13];
            R[arm_fiq_r14] = R[14];
            R[arm_fiq_spsr] = R[arm_spsr];
        }
        break;
        case arm_mode_irq:{
            R[arm_irq_r13] = R[13];
            R[arm_irq_r14] = R[14];
            R[arm_irq_spsr] = R[arm_spsr];
        }
        break;
        case arm_mode_svc:{
            R[arm_svc_r13] = R[13];
            R[arm_svc_r14] = R[14];
            R[arm_svc_spsr] = R[arm_spsr];
        }
        break;
        case arm_mode_abt:{
            R[arm_abt_r13] = R[13];
            R[arm_abt_r14] = R[14];
            R[arm_abt_spsr] = R[arm_spsr];
        }
        break;
        case arm_mode_und:{
            R[arm_und_r13] = R[13];
            R[arm_und_r14] = R[14];
            R[arm_und_spsr] = R[arm_spsr];
        }
        break;
        default:
            break;
        }

        switch (mode)
        {
        case arm_mode_fiq:{
            R[13] = R[arm_fiq_r13];
            R[14] = R[arm_fiq_r14];
            R[arm_spsr] = R[arm_fiq_spsr];
        }
        break;
        case arm_mode_irq:{
            R[13] = R[arm_irq_r13]  ;
            R[14] = R[arm_irq_r14]  ;
            R[arm_spsr] = R[arm_irq_spsr] ;
        }
        break;
        case arm_mode_svc:{
            R[13]       = R[arm_svc_r13]      ;
            R[14]       = R[arm_svc_r14]      ;
            R[arm_spsr] = R[arm_svc_spsr]     ;
        }
        break;
        case arm_mode_abt:{
            R[13] = R[arm_abt_r13] ;
            R[14] = R[arm_abt_r14] ;
            R[arm_spsr] = R[arm_abt_spsr];
        }
        break;
        case arm_mode_und:{
            R[13] = R[arm_und_r13];
            R[14] = R[arm_und_r14];
            R[arm_spsr] = R[arm_und_spsr];
        }
        break;
        default:
            break;
        }
    }
}

static void _msr_mask(uint32_t*R,uint32_t imm,ui mask){
    //模式切换
    //只有模式非用户模式时，才可以切换
    uint32_t cpsr = 0;
    if(((mask>>0)&1)&&(R[arm_mode]!=0b10000)){
        //非用户模式
        uint8_t mode = cpsr & 0x1f;
        cpsr |= imm&0xff;
        _switch_mode(R,mode);
    }
    else{
        //没有更改模式和T标识
        cpsr |= R[arm_mode]&0x1f;
        cpsr |= R[arm_tflag]?1<<5:0;
        cpsr |= R[arm_fflag]?1<<6:0;
        cpsr |= R[arm_iflag]?1<<7:0;
    }

    if((mask>>1)&1){
        cpsr |= imm & 0xff00;
    }

    if((mask>>2)&1){
        cpsr |= imm & 0xff0000;
    }

    if((mask>>3)&1){
        cpsr |= imm & 0xff000000;
        R[arm_nflag] = (imm>>31)&1;
        R[arm_zflag] = (imm>>30)&1;
        R[arm_cflag] = (imm>>29)&1;
        R[arm_vflag] = (imm>>28)&1;
        R[arm_qflag] = (imm>>27)&1;
    }

    // if(R[arm_mode]!=0x10000){
    //     R[arm_mode] =
    // }
}

//msr cpsr,#imm
void msr_imm(uint32_t*R,uint32_t imm){
    #if !NOMSR_MRS
    uint32_t shift_n = imm>>0x8;
    shift_n *= 2;
    imm = Shift(imm&0xff,armo_ror,shift_n);
    _msr(R,imm);
    #else
    cpu_undefined_instructon(R);
    #endif
}

//msr cpsr,rn
void msr(uint32_t*R,ui n){
    #if !NOMSR_MRS
    _msr(R,R[n]);
    #else
    cpu_undefined_instruction(R);
    #endif
}

static void spsr_write(uint32_t*R,uint32_t value,ui mask){
    if((mask>>3)&1){
        R[arm_spsr] &= ~(0xF0000000);
        R[arm_spsr] |= value&0xF0000000;
    }
    if((mask>>2)&1){
        R[arm_spsr] &= ~(0xF<<16);
        R[arm_spsr] |= value&(0xF<<16);
    }
    if((mask>>1)&1){
        R[arm_spsr] &= ~(0xff<<8);
        R[arm_spsr] |= value&(0xFF<<8);
    }
    if(mask&1){
        R[arm_spsr] &= ~(0x7<<5);
        R[arm_spsr] |= value&(0x7<<5);
        //处理模式 if BadMode(Value) UNPREDICTABLE else
        R[arm_spsr] = (R[arm_spsr]&~(0xF))|(value&0xF);
    }
}

void msr_imm_spsr(uint32_t*R,ui mask,uint32_t imm){
    #if !NOMSR_MRS
    uint32_t shift_n = imm>>0x8;
    shift_n *= 2;
    imm = Shift(imm&0xff,armo_ror,shift_n);
    spsr_write(R,imm,mask);
    #else
    cpu_undefined_instruction(R);
    #endif
}

void msr_spsr(uint32_t*R,ui mask,ui n){
    #if !NOMSR_MRS
    spsr_write(R,R[n],mask);
    #else
    cpu_undefined_instruction(R);
    #endif
}

void udf(uint32_t*R,ui imm){
    //未定义指令
}

void nop(uint32_t*R){
    //不运行
}

void _abort(){
    //错误
}

void sdiv(u32*_R,ui rd,ui rn,ui rm){
    s32 *R = (s32*)R;
    R[rd] = R[rn] / R[rm];
}

void udiv(u32*R,ui rd,ui rn,ui rm){
    R[rd] = R[rn] / R[rm];
}

void clz(u32*R,ui rd,ui rm){
    uint32_t value = R[rm];
    int i;
    int result = 1;
    for(i=0;i<32;i++){
        if(value&(1<<31)) result++;
        value<<=1;
    }
    R[rd] = result;
}

void ldrex(u32*R,ui rd,ui rm){
    cpu_undefined_instruction(R);
}

void rrx(u32*R,ui rd,ui rm){
    uint32_t c;
    R[rd] = Shift_C(&c,R[rm],armo_rrx,1,R[arm_cflag]);
}

void rrxS(u32*R,ui rd,ui rm){
    uint32_t c;
    R[rd] = Shift_C(&c,R[rm],armo_rrx,1,R[arm_cflag]);
    R[arm_cflag] = c;
    R[arm_zflag] = R[rd]==0;
    R[arm_nflag] = R[rd]>>31;
}

void sbfx(u32*R,ui d,ui n,ui width,ui lsb){
    int s = 32 - width;
    int32_t value = (int32_t)R[n];
    value >>= lsb;
    value <<= s&0x1f;
    value >>= s&0x1f;
    R[d] = (uint32_t)value;
}

void ubfx(u32*R,ui d,ui n,ui width,ui lsb){
    int s = 32 - width;
    uint32_t value = (uint32_t)R[n];
    value >>= lsb;
    value <<= s&0x1f;
    value >>= s&0x1f;
    R[d] = (uint32_t)value;
}

/*
void t_beq  (uint32_t*R,ui imm){if( R[arm_zflag])jmp_abs(R,                            R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bne  (uint32_t*R,ui imm){if(!R[arm_zflag])jmp_abs(R,                            R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bcs  (uint32_t*R,ui imm){if( R[arm_cflag])jmp_abs(R,                            R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bcc  (uint32_t*R,ui imm){if(!R[arm_cflag])jmp_abs(R,                            R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bmi  (uint32_t*R,ui imm){if( R[arm_nflag])jmp_abs(R,                            R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bpl  (uint32_t*R,ui imm){if(!R[arm_nflag])jmp_abs(R,                            R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bvs  (uint32_t*R,ui imm){if( R[arm_vflag])jmp_abs(R,                            R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bvc  (uint32_t*R,ui imm){if(!R[arm_vflag])jmp_abs(R,                            R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bhi  (uint32_t*R,ui imm){if( R[arm_cflag]&&R[arm_zflag]==0)jmp_abs(R,           R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bls  (uint32_t*R,ui imm){if(!R[arm_cflag]||R[arm_zflag])jmp_abs(R,              R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bge  (uint32_t*R,ui imm){if( R[arm_nflag]==R[arm_vflag])jmp_abs(R,              R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_blt  (uint32_t*R,ui imm){if( R[arm_nflag]!=R[arm_vflag])jmp_abs(R,              R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_bgt  (uint32_t*R,ui imm){if(!R[arm_zflag]&&R[arm_vflag]==R[arm_nflag])jmp_abs(R,R[arm_pc]+((int32_t)(int8_t)imm<<1));}
void t_ble  (uint32_t*R,ui imm){if( R[arm_zflag]||R[arm_vflag]!=R[arm_vflag])jmp_abs(R,R[arm_pc]+((int32_t)(int8_t)imm<<1));}
*/

static ui arm_cond(uint32_t*R,ui cond){
    ui ret = 0;
    switch (cond)
    {

    case 0x0:/*eq*/ ret = R[arm_zflag];break;
    case 0x1:/*ne*/ ret = R[arm_zflag]==0;break;
    case 0x2:/*cs*/ ret = R[arm_cflag];break;
    case 0x3:/*cc*/ ret = R[arm_cflag]==0;break;
    case 0x4:/*mi*/ ret = R[arm_nflag];break;
    case 0x5:/*pl*/ ret = R[arm_nflag]==0;break;
    case 0x6:/*vs*/ ret = R[arm_vflag];break;
    case 0x7:/*vc*/ ret = R[arm_vflag]==0;break;
    #if 0
    //旧代码
    case 0x8:/*hi*/ ret = R[arm_cflag]&&(R[arm_zflag]==0);break;
    case 0x9:/*ls*/ ret = !R[arm_cflag]||R[arm_zflag];break;
    case 0xa:/*ge*/ ret = R[arm_nflag]==R[arm_vflag];break;
    case 0xb:/*lt*/ ret = R[arm_nflag]!=R[arm_vflag];break;
    case 0xc:/*gt*/ ret = !R[arm_zflag]&&(R[arm_vflag]==R[arm_nflag]);break;
    case 0xd:/*le*/ ret = R[arm_zflag]||(R[arm_nflag]!=R[arm_vflag]);break;
    #else
    case 0x8:/*hi*/ ret = R[arm_cflag]&(~R[arm_zflag]);break;
    case 0x9:/*ls*/ ret = ~R[arm_cflag]|R[arm_zflag];break;
    case 0xa:/*ge*/ ret = R[arm_nflag]==R[arm_vflag];break;
    case 0xb:/*lt*/ ret = R[arm_nflag]!=R[arm_vflag];break;
    case 0xc:/*gt*/ ret = ~R[arm_zflag]&(R[arm_vflag]==R[arm_nflag]);break;
    case 0xd:/*le*/ ret = R[arm_zflag] |(R[arm_nflag]!=R[arm_vflag]);break;
    #endif
    default:
        break;
    }
    return ret;
}

static ui arm_handle_cond(uint32_t*R,uint32_t insn,uint32_t mask){
    if(mask<0xF0000000){
        //存在cccc条件
        uint8_t cond = insn>>28;
        if(cond==0xE){
            return 1;
        }
        else{
            ui ret = arm_cond(R,cond);
            if(ret){
                return 1;
            }
            return 0;
        }
    }
    return 1;
}

/*
快速获得 arm 函数指令
*/
#ifdef _ARM_DECODE_
extern void* calloc(unsigned num,unsigned esize);
static void* arm_insntable[0x100] = {0};
uint16_t * arm_insnopcode(uint32_t insn){
    void**ptr = (void**)arm_insntable;
    ui v1 = insn & 0xff;
    ui v2 = (insn >> 0x08) & 0xff;
    ui v3 = (insn >> 0x10) & 0xff;
    ui v4 = (insn >> 0x18) & 0xff;
    if(!ptr[v1]){
        ptr[v1] = calloc(0x100,sizeof(ptr[v1]));
    }
    ptr = (void**)ptr[v1];

    if(!ptr[v2]){
        ptr[v2] = calloc(0x100,sizeof(ptr[v2]));
    }
    ptr = (void**)ptr[v2];

    if(!ptr[v3]){
        ptr[v3] = calloc(0x100,sizeof(ptr[v4]));
    }
    ptr = (void**)ptr[v3];

    uint16_t *code = (uint16_t*)ptr + v4;

    return code;
}

static uint16_t thumb_insntable[0x10000] = {0};
uint16_t *thumb_insnopcode(uint32_t insn){
    ui v1 = insn&0xffff;
#if 0
    thumb_insntable[0] = 0;
    return thumb_insntable+0;
#endif
    return thumb_insntable + v1;
}
#define InstructionPrefix_arm if(arm_handle_cond(R,insn,mask))

#include "arm_exec.h"
#endif //_ARM_DECODE_


intptr_t xadd(intptr_t a1,intptr_t a2){
    return (int32_t)a1+(int32_t)a2;
}
